<!DOCTYPE html><html lang="zh-CN" data-theme="light"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0,viewport-fit=cover"><title>Java | 耶比大熊</title><meta name="author" content="耶比大熊,2324308799@qq.com"><meta name="copyright" content="耶比大熊"><meta name="format-detection" content="telephone=no"><meta name="theme-color" content="ffffff"><meta name="description" content="前后端传参三种传参方式 x-www-form-urlencoded：只能上传键值对，并且键值对都是间隔分开的 multipart&#x2F;form-data：既可以上传文件等二进制数据，也可以上传表单键值对，只是最后会转化为一条信息；  x-www-form-urlencoded： Post传参的默认格式，使用js中URLencode转码方法。包括将name、value中的空格替换为加号；将非">
<meta property="og:type" content="article">
<meta property="og:title" content="Java">
<meta property="og:url" content="https://cxzde.cn/2024/04/01/note-java/index.html">
<meta property="og:site_name" content="耶比大熊">
<meta property="og:description" content="前后端传参三种传参方式 x-www-form-urlencoded：只能上传键值对，并且键值对都是间隔分开的 multipart&#x2F;form-data：既可以上传文件等二进制数据，也可以上传表单键值对，只是最后会转化为一条信息；  x-www-form-urlencoded： Post传参的默认格式，使用js中URLencode转码方法。包括将name、value中的空格替换为加号；将非">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://tuchuang.voooe.cn/images/2024/04/07/background2.jpg">
<meta property="article:published_time" content="2024-04-01T09:00:00.000Z">
<meta property="article:modified_time" content="2024-04-01T09:00:00.000Z">
<meta property="article:author" content="耶比大熊">
<meta property="article:tag" content="blog">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://tuchuang.voooe.cn/images/2024/04/07/background2.jpg"><link rel="shortcut icon" href="/favicon.ico"><link rel="canonical" href="https://cxzde.cn/2024/04/01/note-java/index.html"><link rel="preconnect" href="//cdn.jsdelivr.net"/><link rel="preconnect" href="//busuanzi.ibruce.info"/><link rel="stylesheet" href="/css/index.css?v=4.14.0-b1"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.5.1/css/all.min.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/node-snackbar@0.1.16/dist/snackbar.min.css" media="print" onload="this.media='all'"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fancyapps/ui@5.0.35/dist/fancybox/fancybox.min.css" media="print" onload="this.media='all'"><script>(()=>{
      const saveToLocal = {
        set: (key, value, ttl) => {
          if (ttl === 0) return
          const now = Date.now()
          const expiry = now + ttl * 86400000
          const item = {
            value,
            expiry
          }
          localStorage.setItem(key, JSON.stringify(item))
        },
      
        get: key => {
          const itemStr = localStorage.getItem(key)
      
          if (!itemStr) {
            return undefined
          }
          const item = JSON.parse(itemStr)
          const now = Date.now()
      
          if (now > item.expiry) {
            localStorage.removeItem(key)
            return undefined
          }
          return item.value
        }
      }
      
      window.btf = {
        saveToLocal: saveToLocal,
        getScript: (url, attr = {}) => new Promise((resolve, reject) => {
          const script = document.createElement('script')
          script.src = url
          script.async = true
          script.onerror = reject
          script.onload = script.onreadystatechange = function() {
            const loadState = this.readyState
            if (loadState && loadState !== 'loaded' && loadState !== 'complete') return
            script.onload = script.onreadystatechange = null
            resolve()
          }

          Object.keys(attr).forEach(key => {
            script.setAttribute(key, attr[key])
          })

          document.head.appendChild(script)
        }),

        getCSS: (url, id = false) => new Promise((resolve, reject) => {
          const link = document.createElement('link')
          link.rel = 'stylesheet'
          link.href = url
          if (id) link.id = id
          link.onerror = reject
          link.onload = link.onreadystatechange = function() {
            const loadState = this.readyState
            if (loadState && loadState !== 'loaded' && loadState !== 'complete') return
            link.onload = link.onreadystatechange = null
            resolve()
          }
          document.head.appendChild(link)
        }),

        addGlobalFn: (key, fn, name = false, parent = window) => {
          const pjaxEnable = false
          if (!pjaxEnable && key.startsWith('pjax')) return

          const globalFn = parent.globalFn || {}
          const keyObj = globalFn[key] || {}
    
          if (name && keyObj[name]) return
    
          name = name || Object.keys(keyObj).length
          keyObj[name] = fn
          globalFn[key] = keyObj
          parent.globalFn = globalFn
        }
      }
    
      const activateDarkMode = () => {
        document.documentElement.setAttribute('data-theme', 'dark')
        if (document.querySelector('meta[name="theme-color"]') !== null) {
          document.querySelector('meta[name="theme-color"]').setAttribute('content', '#0d0d0d')
        }
      }
      const activateLightMode = () => {
        document.documentElement.setAttribute('data-theme', 'light')
        if (document.querySelector('meta[name="theme-color"]') !== null) {
          document.querySelector('meta[name="theme-color"]').setAttribute('content', 'ffffff')
        }
      }

      btf.activateDarkMode = activateDarkMode
      btf.activateLightMode = activateLightMode
      
      const t = saveToLocal.get('theme')
    
          const now = new Date()
          const hour = now.getHours()
          const isNight = hour <= 6 || hour >= 18
          if (t === undefined) isNight ? activateDarkMode() : activateLightMode()
          else if (t === 'light') activateLightMode()
          else activateDarkMode()
        
      const asideStatus = saveToLocal.get('aside-status')
      if (asideStatus !== undefined) {
        if (asideStatus === 'hide') {
          document.documentElement.classList.add('hide-aside')
        } else {
          document.documentElement.classList.remove('hide-aside')
        }
      }
    
      const detectApple = () => {
        if(/iPad|iPhone|iPod|Macintosh/.test(navigator.userAgent)){
          document.documentElement.classList.add('apple')
        }
      }
      detectApple()
    })()</script><script>const GLOBAL_CONFIG = {
  root: '/',
  algolia: undefined,
  localSearch: {"path":"/search.xml","preload":false,"top_n_per_article":1,"unescape":false,"languages":{"hits_empty":"找不到您查询的内容：${query}","hits_stats":"共找到 ${hits} 篇文章"}},
  translate: {"defaultEncoding":2,"translateDelay":0,"msgToTraditionalChinese":"繁","msgToSimplifiedChinese":"简"},
  noticeOutdate: {"limitDay":365,"position":"top","messagePrev":"It has been","messageNext":"days since the last update, the content of the article may be outdated."},
  highlight: {"plugin":"highlight.js","highlightCopy":true,"highlightLang":true,"highlightHeightLimit":230},
  copy: {
    success: '复制成功',
    error: '复制错误',
    noSupport: '浏览器不支持'
  },
  relativeDate: {
    homepage: true,
    post: true
  },
  runtime: '天',
  dateSuffix: {
    just: '刚刚',
    min: '分钟前',
    hour: '小时前',
    day: '天前',
    month: '个月前'
  },
  copyright: undefined,
  lightbox: 'fancybox',
  Snackbar: {"chs_to_cht":"你已切换为繁体中文","cht_to_chs":"你已切换为简体中文","day_to_night":"你已切换为深色模式","night_to_day":"你已切换为浅色模式","bgLight":"#49b1f5","bgDark":"#1f1f1f","position":"top-right"},
  infinitegrid: {
    js: 'https://cdn.jsdelivr.net/npm/@egjs/infinitegrid@4.11.1/dist/infinitegrid.min.js',
    buttonText: '加载更多'
  },
  isPhotoFigcaption: false,
  islazyload: true,
  isAnchor: false,
  percent: {
    toc: false,
    rightside: false,
  },
  autoDarkmode: false
}</script><script id="config-diff">var GLOBAL_CONFIG_SITE = {
  title: 'Java',
  isPost: true,
  isHome: false,
  isHighlightShrink: false,
  isToc: true,
  postUpdate: '2024-04-01 17:00:00'
}</script><link rel="stylesheet" href="/css/mouse.css"><link rel="stylesheet" href="/css/iconfont/iconfont.css"><meta name="generator" content="Hexo 7.1.1"></head><body><div id="loading-box"><div class="loading-left-bg"></div><div class="loading-right-bg"></div><div class="spinner-box"><div class="configure-border-1"><div class="configure-core"></div></div><div class="configure-border-2"><div class="configure-core"></div></div><div class="loading-word">加载中...</div></div></div><script>(()=>{
  const $loadingBox = document.getElementById('loading-box')
  const $body = document.body
  const preloader = {
    endLoading: () => {
      $body.style.overflow = ''
      $loadingBox.classList.add('loaded')
    },
    initLoading: () => {
      $body.style.overflow = 'hidden'
      $loadingBox.classList.remove('loaded')
    }
  }

  preloader.initLoading()
  window.addEventListener('load',() => { preloader.endLoading() })

  if (false) {
    btf.addGlobalFn('pjaxSend', () => { preloader.initLoading() }, 'preloader_init')
    btf.addGlobalFn('pjaxComplete', () => { preloader.endLoading() }, 'preloader_end')
  }
})()</script><div id="web_bg"></div><div id="sidebar"><div id="menu-mask"></div><div id="sidebar-menus"><div class="avatar-img is-center"><img src= "" data-lazy-src="/img/avatar.jpg" onerror="onerror=null;src='/img/friend_404.gif'" alt="avatar"/></div><div class="sidebar-site-data site-data is-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">10</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">0</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">0</div></a></div><hr class="custom-hr"/><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> 首页</span></a></div><div class="menus_item"><a class="site-page" href="/archives/"><i class="fa-fw fas fa-archive"></i><span> 归档</span></a></div><div class="menus_item"><a class="site-page" href="/about/"><i class="fa-fw fas fa-heart"></i><span> 关于</span></a></div></div></div></div><div class="post" id="body-wrap"><header class="not-top-img" id="page-header"><nav id="nav"><span id="blog-info"><a href="/" title="耶比大熊"><span class="site-name">耶比大熊</span></a></span><div id="menus"><div id="search-button"><span class="site-page social-icon search"><i class="fas fa-search fa-fw"></i><span> 搜索</span></span></div><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> 首页</span></a></div><div class="menus_item"><a class="site-page" href="/archives/"><i class="fa-fw fas fa-archive"></i><span> 归档</span></a></div><div class="menus_item"><a class="site-page" href="/about/"><i class="fa-fw fas fa-heart"></i><span> 关于</span></a></div></div><div id="toggle-menu"><span class="site-page"><i class="fas fa-bars fa-fw"></i></span></div></div></nav></header><main class="layout" id="content-inner"><div id="post"><div id="post-info"><h1 class="post-title">Java</h1><div id="post-meta"><div class="meta-firstline"><span class="post-meta-date"><i class="far fa-calendar-alt fa-fw post-meta-icon"></i><span class="post-meta-label">发表于</span><time class="post-meta-date-created" datetime="2024-04-01T09:00:00.000Z" title="发表于 2024-04-01 17:00:00">2024-04-01</time><span class="post-meta-separator">|</span><i class="fas fa-history fa-fw post-meta-icon"></i><span class="post-meta-label">更新于</span><time class="post-meta-date-updated" datetime="2024-04-01T09:00:00.000Z" title="更新于 2024-04-01 17:00:00">2024-04-01</time></span></div><div class="meta-secondline"><span class="post-meta-separator">|</span><span class="post-meta-wordcount"><i class="far fa-file-word fa-fw post-meta-icon"></i><span class="post-meta-label">字数总计:</span><span class="word-count">11.5k</span><span class="post-meta-separator">|</span><i class="far fa-clock fa-fw post-meta-icon"></i><span class="post-meta-label">阅读时长:</span><span>46分钟</span></span><span class="post-meta-separator">|</span><span class="post-meta-pv-cv" id="" data-flag-title="Java"><i class="far fa-eye fa-fw post-meta-icon"></i><span class="post-meta-label">阅读量:</span><span id="busuanzi_value_page_pv"><i class="fa-solid fa-spinner fa-spin"></i></span></span></div></div></div><article class="post-content" id="article-container"><hr>
<h2 id="前后端传参"><a href="#前后端传参" class="headerlink" title="前后端传参"></a>前后端传参</h2><h3 id="三种传参方式"><a href="#三种传参方式" class="headerlink" title="三种传参方式"></a>三种传参方式</h3><ul>
<li><p><strong>x-www-form-urlencoded</strong>：只能上传键值对，并且键值对都是间隔分开的</p>
<p><strong>multipart&#x2F;form-data</strong>：既可以上传文件等二进制数据，也可以上传表单键值对，只是最后会转化为一条信息；</p>
</li>
<li><p><strong>x-www-form-urlencoded</strong>： Post传参的默认格式，使用js中URLencode转码方法。包括将name、value中的空格替换为加号；将非ascii字符做百分号编码；将input的name、value用‘&#x3D;’连接，不同的input之间用‘&amp;’连接。这种post格式跟get的区别在于：get把转换、拼接完的字符串用‘?’直接与表单的action连接作为URL使用，所以请求体里没有数据；而post把转换、拼接后的字符串放在了请求体里，不会在浏览器的地址栏显示，因而更安全一些。对于一段utf8编码的字节，用application&#x2F;x-www-form-urlencoded传输其中的ascii字符没有问题，但对于非ascii字符传输效率就很低了，因此在传很长的字节（如文件）时应用multipart&#x2F;form-data格式。smtp等协议也使用或借鉴了此格式。</p>
<p><strong>multipart&#x2F;form-data</strong>：将表单中的每个input转为了一个由boundary分割的小格式，没有转码，直接将utf8字节拼接到请求体中，在本地有多少字节实际就发送多少字节，极大提高了效率，适合传输长字节。</p>
<p><strong>json</strong>：现在很多时候也把它作为请求头，用来告诉服务端消息主体是序列化的JSON字符串，除了低版本的IE，基本都支持。除了低版本的IE都支持JSON.stringify（）的方法，服务端也有处理JSON的函数，使用JSON不会有任何麻烦。</p>
</li>
<li><p>当传入参数是x-www-form-urlencoded，接收参数@RequestBody+ String&#x2F;Map&#x2F;LinkedHashMap即可接收成功</p>
</li>
</ul>
<h3 id="post和get请求"><a href="#post和get请求" class="headerlink" title="post和get请求"></a>post和get请求</h3><ul>
<li>发送get请求将参数通过？拼接在url后面</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line">$.ajax(&#123;</span><br><span class="line">        url: <span class="string">&quot;/order/userPage?page=&quot;</span>+page+<span class="string">&quot;&amp;pageSize=&quot;</span>+pageSize,    <span class="comment">//请求的url地址  </span></span><br><span class="line">        cache: <span class="string">&quot;false&quot;</span>,   <span class="comment">//设置为false将不会从浏览器中加载请求信息</span></span><br><span class="line">        async: <span class="string">&quot;true&quot;</span>,    <span class="comment">//true所有请求均为异步请求</span></span><br><span class="line">        dataType: <span class="string">&quot;json&quot;</span>, <span class="comment">//请求返回数据的格式</span></span><br><span class="line">        type:<span class="string">&quot;get&quot;</span>,      <span class="comment">//请求方式</span></span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line"><span class="comment">//上面等同于==&gt;&gt;</span></span><br><span class="line">async <span class="title function_">initData</span><span class="params">()</span>&#123;</span><br><span class="line">   paging: &#123;</span><br><span class="line">      page: <span class="number">1</span>,</span><br><span class="line">      pageSize: <span class="number">5</span></span><br><span class="line">   &#125;</span><br><span class="line">   <span class="type">const</span> <span class="variable">res</span> <span class="operator">=</span> await <span class="title function_">orderPagingApi</span><span class="params">(<span class="built_in">this</span>.paging)</span> </span><br><span class="line">&#125;</span><br><span class="line">function <span class="title function_">orderPagingApi</span><span class="params">(data)</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> $axios(&#123;</span><br><span class="line">        <span class="string">&#x27;url&#x27;</span>: <span class="string">&#x27;/order/userPage&#x27;</span>,</span><br><span class="line">        <span class="string">&#x27;method&#x27;</span>: <span class="string">&#x27;get&#x27;</span>,</span><br><span class="line">        <span class="comment">//请求参数</span></span><br><span class="line">        params: &#123;...data&#125;</span><br><span class="line">    &#125;)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 上面等同于==&gt;&gt;</span></span><br><span class="line">async <span class="title function_">initData</span><span class="params">()</span>&#123;</span><br><span class="line">   paging: &#123;</span><br><span class="line">      page: <span class="number">1</span>,</span><br><span class="line">      pageSize: <span class="number">5</span></span><br><span class="line">   &#125;</span><br><span class="line">   <span class="type">const</span> <span class="variable">res</span> <span class="operator">=</span> await <span class="title function_">orderPagingApi</span><span class="params">(<span class="built_in">this</span>.paging)</span> </span><br><span class="line">&#125;</span><br><span class="line">function <span class="title function_">orderPagingApi</span><span class="params">(data)</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> $axios(&#123;</span><br><span class="line">        <span class="string">&#x27;url&#x27;</span>: <span class="string">&#x27;/order/userPage&#x27;</span>,</span><br><span class="line">        <span class="string">&#x27;method&#x27;</span>: <span class="string">&#x27;get&#x27;</span>,</span><br><span class="line">        <span class="string">&#x27;data&#x27;</span>: data</span><br><span class="line">    &#125;)</span><br><span class="line">&#125;</span><br><span class="line">    </span><br><span class="line"><span class="comment">// 后端接收参数   @RequestParam 可加可不加</span></span><br><span class="line"><span class="meta">@GetMapping(&quot;/xxx&quot;)</span></span><br><span class="line"><span class="keyword">public</span> R&lt;xxx&gt; <span class="title function_">userPage</span><span class="params">(<span class="meta">@RequestParam(&quot;page&quot;)</span>Integer page,Integer pageSize)</span>&#123;&#125;</span><br></pre></td></tr></table></figure>

<ul>
<li>将参数拼接在url中，后台通过占位符接收参数  &#x2F;{id}，前端传递参数直接将参数拼在url中，如 &#x2F;xxx&#x2F;1</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">async <span class="title function_">initData</span><span class="params">()</span>&#123;</span><br><span class="line">    <span class="type">const</span> <span class="variable">res</span> <span class="operator">=</span> await <span class="title function_">addressFindOneApi</span><span class="params">(params.id)</span></span><br><span class="line">&#125;</span><br><span class="line">function <span class="title function_">addressFindOneApi</span><span class="params">(id)</span> &#123;</span><br><span class="line">  <span class="keyword">return</span> $axios(&#123;</span><br><span class="line">    <span class="string">&#x27;url&#x27;</span>: `/addressBook/$&#123;id&#125;`,</span><br><span class="line">    <span class="string">&#x27;method&#x27;</span>: <span class="string">&#x27;get&#x27;</span>,</span><br><span class="line">  &#125;)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 后端接收参数</span></span><br><span class="line"><span class="meta">@GetMapping(&quot;/xxx/&#123;id&#125;&quot;)</span></span><br><span class="line"><span class="keyword">public</span> R&lt;xxx&gt; <span class="title function_">backList</span><span class="params">(<span class="meta">@PathVariable(&quot;id&quot;)</span>Long id)</span>&#123;&#125;</span><br><span class="line"><span class="comment">// @PathVariable:需要接收前端传递的参数必须要加上这个注解</span></span><br><span class="line"><span class="comment">// @PathVariable(name=&quot;&quot;)和@PathVariable(value=&quot;&quot;)都可以</span></span><br><span class="line"><span class="comment">// 可以@RequestMapping或@GetMapping。如果用@RequestMapping就应为：@RequestMapping(value = &quot;xxx/&#123;id&#125;&quot;, method= RequestMethod.GET)</span></span><br></pre></td></tr></table></figure>

<ul>
<li>通过post提交方式将form表单中的数据序列化后传递到后台</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">async <span class="title function_">initData</span><span class="params">()</span>&#123;</span><br><span class="line">    <span class="type">const</span> <span class="variable">res</span> <span class="operator">=</span>await <span class="title function_">formAjax</span><span class="params">()</span>;</span><br><span class="line">&#125;</span><br><span class="line">function <span class="title function_">formAjax</span><span class="params">()</span> &#123;</span><br><span class="line">    $.ajax(&#123;</span><br><span class="line">        url: <span class="string">&quot;/login&quot;</span>,  </span><br><span class="line">        type: <span class="string">&quot;post&quot;</span>, </span><br><span class="line">        data: $(<span class="string">&quot;#form&quot;</span>).serialize(),  <span class="comment">// 对id为form的表单数据进行序列化并传递到后台</span></span><br><span class="line">    &#125;)</span><br><span class="line">&#125; </span><br><span class="line"><span class="comment">//后端接收参数</span></span><br><span class="line"><span class="meta">@RequestMapping(&quot;/login&quot;)</span></span><br><span class="line"><span class="comment">//form表单的数据与User实体类的数据相对应</span></span><br><span class="line"><span class="keyword">public</span> String <span class="title function_">login</span> <span class="params">(User user)</span> &#123;&#125;</span><br></pre></td></tr></table></figure>

<ul>
<li>通过post提交方式将form表单的类型是 json</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">async <span class="title function_">initData</span><span class="params">()</span>&#123;</span><br><span class="line">    <span class="type">const</span> <span class="variable">res</span> <span class="operator">=</span>await <span class="title function_">formAjax</span><span class="params">()</span>;</span><br><span class="line">&#125;</span><br><span class="line"> </span><br><span class="line">function <span class="title function_">formAjax</span><span class="params">()</span> &#123;</span><br><span class="line">     $.ajax(&#123;</span><br><span class="line">       url: <span class="string">&quot;/login&quot;</span>, </span><br><span class="line">       type: <span class="string">&quot;post&quot;</span>, </span><br><span class="line">       contentType: <span class="string">&#x27;application/json&#x27;</span>,</span><br><span class="line">     &#125;)</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//后端接收参数</span></span><br><span class="line"><span class="meta">@RequestMapping(&quot;/login&quot;)</span></span><br><span class="line"><span class="comment">//form表单的数据与User实体类的数据相对应</span></span><br><span class="line"><span class="keyword">public</span> String <span class="title function_">login</span> <span class="params">(<span class="meta">@RequestBody</span> User user)</span> &#123;&#125;</span><br></pre></td></tr></table></figure>

<ul>
<li>前台将普通数据转换为json</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//后台接收参数 map或对应实体</span></span><br><span class="line"><span class="meta">@GetMapping(&quot;/xxx/xxx&quot;)</span></span><br><span class="line"><span class="keyword">public</span> R&lt;xxx&gt; <span class="title function_">userPage</span><span class="params">(<span class="meta">@RequesBody</span> Map&lt;Integer,Integer&gt; map)</span>&#123;</span><br><span class="line">      <span class="type">Integer</span> <span class="variable">page</span> <span class="operator">=</span> map.get(<span class="string">&quot;page&quot;</span>);        </span><br><span class="line">      <span class="type">Integer</span> <span class="variable">pageSize</span> <span class="operator">=</span> map.get(<span class="string">&quot;pageSize&quot;</span>);    </span><br><span class="line">&#125;async <span class="title function_">initData</span><span class="params">()</span>&#123;</span><br><span class="line">   paging: &#123;</span><br><span class="line">      page: <span class="number">1</span>,</span><br><span class="line">      pageSize: <span class="number">5</span></span><br><span class="line">   &#125;</span><br><span class="line">   <span class="type">const</span> <span class="variable">res</span> <span class="operator">=</span> await <span class="title function_">orderPagingApi</span><span class="params">(<span class="built_in">this</span>.paging)</span> </span><br><span class="line">&#125;</span><br><span class="line">function <span class="title function_">orderPagingApi</span><span class="params">(data)</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> $axios(&#123;</span><br><span class="line">        <span class="string">&#x27;url&#x27;</span>: <span class="string">&#x27;/order/userPage&#x27;</span>,</span><br><span class="line">        <span class="string">&#x27;method&#x27;</span>: <span class="string">&#x27;post&#x27;</span>, </span><br><span class="line">         data: JSON.stringify(data),</span><br><span class="line">    &#125;)</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//后台接收参数 map或对应实体</span></span><br><span class="line"><span class="meta">@GetMapping(&quot;/xxx/xxx&quot;)</span></span><br><span class="line"><span class="keyword">public</span> R&lt;xxx&gt; <span class="title function_">userPage</span><span class="params">(<span class="meta">@RequesBody</span> Map&lt;Integer,Integer&gt; map)</span>&#123;</span><br><span class="line">      <span class="type">Integer</span> <span class="variable">page</span> <span class="operator">=</span> map.get(<span class="string">&quot;page&quot;</span>);        </span><br><span class="line">      <span class="type">Integer</span> <span class="variable">pageSize</span> <span class="operator">=</span> map.get(<span class="string">&quot;pageSize&quot;</span>);    </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<ul>
<li><p>接收参数出错案例</p>
<p>Cannot deserialize instance of <code>java.lang.String</code> out of START_OBJECT token，请求体中的 user 被认为是一个Object对象，不能用String进行解析</p>
</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//修改前</span></span><br><span class="line"><span class="meta">@PostMapping(&quot;/regiest&quot;)</span></span><br><span class="line"><span class="keyword">public</span> R&lt;String&gt; <span class="title function_">createUser</span><span class="params">(<span class="meta">@RequestBody</span> Map&lt;String,String&gt; map)</span> &#123;&#125;</span><br><span class="line"><span class="comment">//修改后</span></span><br><span class="line"><span class="meta">@PostMapping(&quot;/regiest&quot;)</span></span><br><span class="line"><span class="keyword">public</span> R&lt;String&gt; <span class="title function_">createUser</span><span class="params">(<span class="meta">@RequestBody</span> Map&lt;String,Object&gt; map)</span> &#123;&#125;</span><br></pre></td></tr></table></figure>

<ul>
<li>前端传参 {params: params} ,后端用 @RequestParams(“id”) 接参</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//前端发送数据</span></span><br><span class="line"><span class="built_in">this</span>.$axios</span><br><span class="line">       .delete(<span class="string">&quot;login/deleteUserInfo&quot;</span>, </span><br><span class="line">        &#123; </span><br><span class="line">    		params: &#123;</span><br><span class="line">               userId: <span class="built_in">this</span>.id</span><br><span class="line">          	&#125; </span><br><span class="line">		&#125;)</span><br><span class="line">       .then(</span><br><span class="line">         <span class="built_in">this</span>.$message(&#123;</span><br><span class="line">         type: <span class="string">&quot;success&quot;</span>,</span><br><span class="line">         message: <span class="string">&quot;删除用户信息成功&quot;</span>,</span><br><span class="line">      &#125;))</span><br><span class="line">       .<span class="keyword">catch</span>(</span><br><span class="line">        <span class="built_in">this</span>.$message(&#123;</span><br><span class="line">        type: <span class="string">&quot;false&quot;</span>,</span><br><span class="line">        message: <span class="string">&quot;删除用户信息失败&quot;</span>,</span><br><span class="line">      &#125;)</span><br><span class="line"><span class="comment">//后端接收数据</span></span><br><span class="line"><span class="meta">@DeleteMapping(&quot;xxx&quot;)</span></span><br><span class="line"><span class="keyword">public</span> R <span class="title function_">deleteUserInfo</span><span class="params">(<span class="meta">@RequestParam(&quot;userId&quot;)</span> String userId)</span>&#123;&#125;</span><br></pre></td></tr></table></figure>

<ul>
<li>前端通过 {data : param} 传参，后端通过 @RequestBody 接参</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//前端</span></span><br><span class="line">deleteMessage() &#123;</span><br><span class="line">    axios.delete(<span class="string">&#x27;login/deleteUserInfo&#x27;</span>, </span><br><span class="line">                 &#123; data : &#123;</span><br><span class="line">                     userId: <span class="built_in">this</span>.id</span><br><span class="line">                 &#125;&#125;).then((response) =&gt; &#123;</span><br><span class="line">    &#125;);</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//后端</span></span><br><span class="line"><span class="meta">@DeleteMapping(&quot;deleteUserInfo&quot;)</span></span><br><span class="line"><span class="keyword">public</span> R <span class="title function_">deleteUserInfo</span><span class="params">(<span class="meta">@RequestBody</span> String userId)</span>&#123;&#125;</span><br></pre></td></tr></table></figure>

<ul>
<li>el-select 数据回显问题</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">&lt;!-- :value=&#x27;1&#x27; v-model=&quot;1&quot;（数值 1）则匹配(number=number string=string类型要一致),显示label,否则显示value--&gt;</span><br><span class="line">&lt;el-form-item label=&quot;角色名称：&quot; label-width=&quot;100px&quot;&gt;</span><br><span class="line">	&lt;el-select</span><br><span class="line">        placeholder=&quot;请选择角色名称&quot;</span><br><span class="line">        v-model=&quot;form.roleId&quot;</span><br><span class="line">        :label-width=&quot;formLabelWidth&quot;</span><br><span class="line">        style=&quot;width: 200px&quot;</span><br><span class="line">    &gt;</span><br><span class="line">		&lt;el-option</span><br><span class="line">            v-for=&quot;item in roleInfo&quot;</span><br><span class="line">            :key=&quot;item.value&quot;</span><br><span class="line">            :label=&quot;item.roleName&quot;</span><br><span class="line">            :value=&quot;item.roleId&quot;</span><br><span class="line">		&gt;            </span><br><span class="line">		&lt;/el-option&gt;</span><br><span class="line">	&lt;/el-select&gt;</span><br><span class="line">&lt;/el-form-item&gt;</span><br></pre></td></tr></table></figure>



<hr>
<h2 id="ajax请求"><a href="#ajax请求" class="headerlink" title="ajax请求"></a>ajax请求</h2><h3 id="ajax请求规范"><a href="#ajax请求规范" class="headerlink" title="ajax请求规范"></a>ajax请求规范</h3><ul>
<li>axios普通get请求</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">test</span>(<span class="params">value</span>) &#123;</span><br><span class="line">  <span class="title function_">axios</span>(&#123;</span><br><span class="line">    <span class="comment">//请求方式</span></span><br><span class="line">    <span class="attr">method</span>:<span class="string">&#x27;get&#x27;</span>,</span><br><span class="line">    <span class="comment">//后端接口路径</span></span><br><span class="line">    <span class="attr">url</span>:<span class="string">&#x27;/xxx&#x27;</span>,</span><br><span class="line">    <span class="comment">//注意这里使用的是params,该属性负责把属性名和属性值添加到url后面，一般和get配合使用，但也能和post配合使用</span></span><br><span class="line">    <span class="attr">params</span>: &#123;</span><br><span class="line">      <span class="comment">//attributeName为属性名，value为属性值</span></span><br><span class="line">      <span class="attr">attributeName</span>:value</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;).<span class="title function_">then</span>(<span class="function">(<span class="params">response</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="comment">//response是一个返回的promise对象，该注释所在的这行一般对该promise对象进行处理从而获取数据</span></span><br><span class="line">  &#125;).<span class="title function_">catch</span>(<span class="function">(<span class="params">error</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="comment">//对error进行处理</span></span><br><span class="line">  &#125;)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//普通get请求时对应的接收</span></span><br><span class="line"><span class="meta">@GetMapping(&quot;/xxx&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">test</span><span class="params">(<span class="meta">@RequestParam(value = &quot;attributeName&quot;)</span> String attributeName)</span>&#123;</span><br><span class="line"><span class="comment">//axios使用params进行传值，而Java就需要用到@RequestParam来接收params的值，value后的值要对应上params里的属性名,即attributeName，若不写，则value默认为String后的attributeName这一属性名，而且一个请求能拥有多个@RequestParam</span></span><br><span class="line">&#125;		</span><br></pre></td></tr></table></figure>

<ul>
<li>axios使用 restful 规范的get请求</li>
</ul>
<blockquote>
<p>路径后面有反斜杠’&#x2F; ‘，不要写漏了，不然value就会变成路径的一部分，请求路径就会变成&#x2F;xxx后面跟上value的值，导致404。</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">test</span>(<span class="params">value</span>) &#123;</span><br><span class="line">  <span class="title function_">axios</span>(&#123;</span><br><span class="line">    <span class="comment">//请求方式</span></span><br><span class="line">    <span class="attr">method</span>:<span class="string">&#x27;get&#x27;</span>,</span><br><span class="line">    <span class="comment">//后端接口路径+属性值</span></span><br><span class="line">    <span class="attr">url</span>:<span class="string">&#x27;/xxx/&#x27;</span>+value,</span><br><span class="line">  &#125;).<span class="title function_">then</span>(<span class="function">(<span class="params">response</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="comment">//response是一个返回的promise对象，该注释所在的这行一般对该promise对象进行处理从而获取数据</span></span><br><span class="line">  &#125;).<span class="title function_">catch</span>(<span class="function">(<span class="params">error</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="comment">//对error进行处理</span></span><br><span class="line">  &#125;)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@GetMapping(&quot;/xxx/&#123;id&#125;&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">test</span><span class="params">(<span class="meta">@PathVariable(&quot;id&quot;)</span> String()</span> attributeName)&#123;</span><br><span class="line"><span class="comment">//axios使用restful的方式进行传值，而Java就需要用到@PathVariable来接收url后的值，/xxx/&#123;id&#125;里的id必须和@PathVariable(&quot;id&quot;)里的id名字一致，而且一个请求能拥有多个@PathVariable</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<ul>
<li>axios使用post+params请求</li>
</ul>
<blockquote>
<p>除了method的请求方式和接收请求用@PostMapping，其他都和普通的get请求一致</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">test</span>(<span class="params">value</span>) &#123;</span><br><span class="line">  <span class="title function_">axios</span>(&#123;</span><br><span class="line">    <span class="comment">//请求方式</span></span><br><span class="line">    <span class="attr">method</span>:<span class="string">&#x27;post&#x27;</span>,</span><br><span class="line">    <span class="comment">//后端接口路径</span></span><br><span class="line">    <span class="attr">url</span>:<span class="string">&#x27;/xxx&#x27;</span>,</span><br><span class="line">    <span class="comment">//注意这里使用的是params,该属性负责把属性名和属性值添加到url后面，一般和get配合使用，但也能和post配合使用</span></span><br><span class="line">    <span class="attr">params</span>: &#123;</span><br><span class="line">      <span class="comment">//attributeName为属性名，value为属性值</span></span><br><span class="line">      <span class="attr">attributeName</span>:value</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;).<span class="title function_">then</span>(<span class="function">(<span class="params">response</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="comment">//response是一个返回的promise对象，该注释所在的这行一般对该promise对象进行处理从而获取数据</span></span><br><span class="line">  &#125;).<span class="title function_">catch</span>(<span class="function">(<span class="params">error</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="comment">//对error进行处理</span></span><br><span class="line">  &#125;)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@PostMapping(&quot;/xxx&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">test</span><span class="params">(<span class="meta">@RequestParam(value = &quot;attributeName&quot;)</span> String attributeName)</span>&#123;</span><br><span class="line">    <span class="comment">//axios使用params进行传值，而Java就需要用到@RequestParam来接收params的值，value后的值要对应上params里的属性名，即	attributeName，若不写，则value默认为String后的attributeName这一属性名，而且一个请求能拥有多个@RequestParam</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<ul>
<li>axios使用post+data请求</li>
</ul>
<blockquote>
<p>注意：obj对象里的属性名要和people实体类里的属性名一样，因为obj对象里的属性名与people实体类里的属性名匹配时，大小写敏感，即区分大小写。</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//方法名为test,传入js对象obj,js对象放属性和属性值,例如obj:&#123;userName:张三，age:18&#125;</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">test</span>(<span class="params">obj</span>) &#123;</span><br><span class="line">  <span class="title function_">axios</span>(&#123;</span><br><span class="line">    <span class="comment">//请求方式</span></span><br><span class="line">    <span class="attr">method</span>:<span class="string">&#x27;post&#x27;</span>,</span><br><span class="line">    <span class="comment">//后端接口路径</span></span><br><span class="line">    <span class="attr">url</span>:<span class="string">&#x27;/xxx&#x27;</span>,</span><br><span class="line">    <span class="comment">//注意这里是data,该属性负责把属性名和属性值添加到请求体里面，一般和post配合使用,而且不要用&#123;&#125;把obj对象包裹起来，不然后端无法解析前端传过来的JSON</span></span><br><span class="line">    <span class="attr">data</span>: obj</span><br><span class="line">  &#125;).<span class="title function_">then</span>(<span class="function">(<span class="params">response</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="comment">//response是一个返回的promise对象，该注释所在的这行一般对该promise对象进行处理从而获取数据</span></span><br><span class="line">  &#125;).<span class="title function_">catch</span>(<span class="function">(<span class="params">error</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="comment">//对error进行处理</span></span><br><span class="line">  &#125;)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//对应的People实体类</span></span><br><span class="line"><span class="meta">@Data</span>  </span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">People</span>&#123;</span><br><span class="line">    <span class="keyword">private</span> String userName;</span><br><span class="line">    <span class="keyword">private</span> Integer age;   </span><br><span class="line">&#125;</span><br><span class="line"><span class="meta">@PostMapping(&quot;/xxx&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">test</span><span class="params">(<span class="meta">@RequestBody</span> People people)</span>&#123;</span><br><span class="line">    <span class="comment">//axios使用post+data进行传值，而Java就需要用到@RequestBody来接收data的值，obj里的属性名与people实体类的属性名相同，	obj里的属性名和people的属性名就能进行动态绑定从而把obj的属性值set进people实体类里，而一个请求只能拥有一个@RequestBody；	注意！！！obj对象里的属性名一定得和people实体类里的属性名一模一样，因为obj对象里的属性名与people实体类里的属性名匹配时，	 大小写敏感，即区分大小写</span></span><br></pre></td></tr></table></figure>

<h3 id="传参问题"><a href="#传参问题" class="headerlink" title="传参问题"></a>传参问题</h3><ul>
<li><p>@RequestBody传参</p>
<p>当接口默认使用@RequestBody传参时，每一个请求必须通过实体对象进行传参，不能使用form-data表单的方式进行传参。</p>
<p><strong>解决方案有两种：</strong></p>
<p>① 改成json方式提交；</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">  <span class="attr">&quot;knowledgeSort&quot;</span> <span class="punctuation">:</span> <span class="string">&quot; &quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;knowledgeParentId&quot;</span><span class="punctuation">:</span> <span class="string">&quot; &quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;knowledgeName&quot;</span><span class="punctuation">:</span> <span class="string">&quot; &quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;chapterId&quot;</span><span class="punctuation">:</span> <span class="string">&quot; &quot;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure></li>
</ul>
<p>​		② 把接口的@RequestBody 注解去掉;</p>
<ul>
<li><p>Postman传参方式</p>
<p>第一种是使用 raw：</p>
<p><img src= "" data-lazy-src="https://cdn.jsdelivr.net/gh/cxz206015/For-PicGo@main/img/1669888061090.jpg" alt="img"></p>
<p>第二种是使用 form-data：</p>
<p><img src= "" data-lazy-src="https://cdn.jsdelivr.net/gh/cxz206015/For-PicGo@main/img/20180515104528896.png" alt="img"></p>
<p>第三种是直接使用变量的方式：</p>
<p><img src= "" data-lazy-src="https://cdn.jsdelivr.net/gh/cxz206015/For-PicGo@main/img/20180515104010153.png" alt="img"></p>
</li>
</ul>
<hr>
<h2 id="日志"><a href="#日志" class="headerlink" title="日志"></a>日志</h2><h3 id="日志框架和日志门面"><a href="#日志框架和日志门面" class="headerlink" title="日志框架和日志门面"></a>日志框架和日志门面</h3><ul>
<li><p>常见的日志框架</p>
<p><strong>Log4j</strong>：Apache Log4j 是一个广泛使用的日志框架，它提供了丰富的配置选项和多种输出目标。</p>
<p><strong>Log4j2</strong>: Apache Log4j 2 是 Apache Software Foundation 开发的日志框架，它是 Log4j 的升级版本，提供了更好的性能和功能。</p>
<p><strong>Logback</strong>：Logback 是由 Log4j 的创始人设计的日志框架，旨在取代 Log4j。它在性能和灵活性方面表现出色。</p>
<p><strong>JUL</strong>： (Java Util Logging) JUL 是 Java 平台自带的日志框架，位于<code>java.util.logging</code>包下。它是标准的 Java 日志框架，使用简单，但功能相对较弱。</p>
</li>
<li><p>常见的日志门面</p>
<p><strong>SLF4J：</strong>常见的日志门面，它提供了统一的日志 API，并允许你在项目中使用 SLF4J 的接口，而不用直接依赖于具体的日志实现。</p>
<p><strong>ACL：</strong>(Apache Commons Logging)常见的日志门面，类似于 SLF4J，它允许开发者使用通用的 API 来进行日志记录。</p>
</li>
</ul>
<blockquote>
<p><strong>注意</strong>：日志门面是一个抽象层，它提供了一组通用的日志 API，可以将这些 API 与不同的日志框架进行绑定。这样，你可以在项目中使用统一的日志 API，而无需直接和特定的日志框架耦合。根据项目需求和个人喜好，可以选择使用不同的日志门面和底层的日志实现。其中，SLF4J 是目前使用最广泛的日志门面之一，并且很多日志框架都支持与 SLF4J 的集成</p>
</blockquote>
<h3 id="日志如何使用"><a href="#日志如何使用" class="headerlink" title="日志如何使用"></a>日志如何使用</h3><p>两个步骤：<strong>引入依赖</strong>和<strong>配置日志框架</strong></p>
<ul>
<li><p>引入依赖：</p>
<p>首先，你需要在项目的构建工具（如Maven、Gradle等）中添加对日志门面和具体日志框架的依赖。以 SLF4J 和 Logback 为例，在 Maven 中的依赖配置如下：</p>
</li>
</ul>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- SLF4J 日志门面 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.slf4j<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>slf4j-api<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.7.32<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!-- Logback 日志框架 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>ch.qos.logback<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>logback-classic<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.2.6<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>

<ul>
<li><p>配置日志框架：</p>
<p>日志框架的配置方式因框架而异。对于 Logback，需要创建一个 <code>logback.xml</code>配置文件，并放在项目的 classpath 路径下( 通常是<code>src/main/resources</code> 目录下)，以下是一个简单的 Logback 配置示例，用于将日志输出到控制台：</p>
</li>
</ul>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- logback.xml --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">configuration</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">appender</span> <span class="attr">name</span>=<span class="string">&quot;CONSOLE&quot;</span> <span class="attr">class</span>=<span class="string">&quot;ch.qos.logback.core.ConsoleAppender&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">encoder</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">pattern</span>&gt;</span>%d&#123;yyyy-MM-dd HH:mm:ss.SSS&#125; [%thread] %-5level %logger&#123;36&#125; - %msg%n<span class="tag">&lt;/<span class="name">pattern</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">encoder</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">appender</span>&gt;</span></span><br><span class="line"></span><br><span class="line">  <span class="tag">&lt;<span class="name">root</span> <span class="attr">level</span>=<span class="string">&quot;debug&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">appender-ref</span> <span class="attr">ref</span>=<span class="string">&quot;CONSOLE&quot;</span> /&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">root</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">configuration</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>上述配置定义了一个输出到控制台的 Appender，并将根日志记录器的级别设置为 <code>debug</code>，这意味着会记录所有级别的日志信息。</p>
<p>一旦你完成了依赖的引入和日志框架的配置，你就可以在项目中使用日志门面的 API（例如 SLF4J 提供的 <code>Logger</code> 接口）来记录日志。根据日志门面的 API 设计，你可以使用不同的日志级别（如 <code>debug</code>、<code>info</code>、<code>warn</code>、<code>error</code> 等）和相应的日志方法来记录不同级别的日志信息。</p>
<p>例如，在代码中使用 SLF4J 来记录日志：当项目运行时，具体的日志输出将由你在配置文件中指定的 Appender 和日志级别来决定。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> org.slf4j.Logger;</span><br><span class="line"><span class="keyword">import</span> org.slf4j.LoggerFactory;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyClass</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">Logger</span> <span class="variable">logger</span> <span class="operator">=</span> LoggerFactory.getLogger(MyClass.class);</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">doSomething</span><span class="params">()</span> &#123;</span><br><span class="line">        logger.debug(<span class="string">&quot;This is a debug message.&quot;</span>);</span><br><span class="line">        logger.info(<span class="string">&quot;This is an info message.&quot;</span>);</span><br><span class="line">        logger.warn(<span class="string">&quot;This is a warning message.&quot;</span>);</span><br><span class="line">        logger.error(<span class="string">&quot;This is an error message.&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<blockquote>
<p>在项目中集成日志门面和日志框架，首先引入相应的依赖（日志门面和具体日志框架的实现），然后配置日志框架以指定日志输出的方式和级别。在代码中，你可以使用日志门面的 API 来记录日志。这样可以在不改变代码的情况下切换不同的日志框架，以满足项目的日志需求</p>
</blockquote>
<hr>
<h2 id="异常"><a href="#异常" class="headerlink" title="异常"></a>异常</h2><p>try-with-resource语法</p>
<p>后续补充细节…</p>
<h2 id="网络编程"><a href="#网络编程" class="headerlink" title="网络编程"></a>网络编程</h2><p><code>Socket</code>：套接字，是计算机网络编程中的一个核心概念，它提供了一种跨网络进程间通信（IPC, Inter-Process Communication）的机制。Socket允许两个不同计算机上的应用程序通过网络进行数据交换，就像两个程序在同一条线上“对话”一样。这一概念广泛应用于互联网通信、分布式系统以及各种客户端-服务器模型的程序中。</p>
<h3 id="Socket的基本原理"><a href="#Socket的基本原理" class="headerlink" title="Socket的基本原理"></a>Socket的基本原理</h3><p>Socket基于客户端-服务器模型工作，主要涉及以下几个关键点：</p>
<ol>
<li>地址家族：指定通信的地址类型，如IPv4、IPv6等。</li>
<li>套接字类型：主要有流式套接字（Stream Socket，对应TCP协议）和数据报套接字（Datagram Socket，对应UDP协议）两种。流式套接字提供双向的、有序的、无重复的数据流服务，保证数据的可靠传输；而数据报套接字则是无连接的，不保证数据的顺序和可靠性，但传输效率较高。</li>
<li>通信协议：最常用的是 <code>TCP</code> （Transmission Control Protocol，传输控制协议）和 <code>UDP</code> （User Datagram Protocol，用户数据报协议）。</li>
</ol>
<h3 id="Socket的典型用途"><a href="#Socket的典型用途" class="headerlink" title="Socket的典型用途"></a>Socket的典型用途</h3><ul>
<li>Web服务：HTTP服务器与浏览器之间的通信通常基于TCP Socket。</li>
<li>文件传输：FTP、某些类型的下载和上传服务依赖TCP Socket保证数据的完整传输。</li>
<li>即时通讯：如聊天应用，可能使用TCP Socket保持稳定的连接或使用UDP Socket实现实时性较高的消息传递。</li>
<li>在线游戏：游戏服务器与客户端间的实时交互，可能结合TCP和UDP，TCP用于确保重要指令的可靠传输，UDP用于低延迟的游戏状态更新。</li>
<li>分布式计算：在分布式系统中，不同节点间的数据交换可能通过Socket实现。</li>
</ul>
<h3 id="使用流程"><a href="#使用流程" class="headerlink" title="使用流程"></a>使用流程</h3><ol>
<li>创建Socket：客户端和服务器端都需要创建Socket实例。</li>
<li>绑定与监听：服务器端Socket需要绑定到一个IP地址和端口号上，并开始监听来自客户端的连接请求。</li>
<li>连接：客户端Socket尝试连接到服务器的指定地址和端口。</li>
<li>数据交换：连接建立后，双方可以通过输入输出流进行数据的发送和接收。</li>
<li>关闭Socket：数据交换完毕后，关闭Socket释放资源。</li>
</ol>
<p>Socket编程为开发者提供了灵活的网络通信能力，是构建网络应用的基础。</p>
<hr>
<h2 id="集合"><a href="#集合" class="headerlink" title="集合"></a>集合</h2><h3 id="List"><a href="#List" class="headerlink" title="List"></a>List</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 为什么推荐第一种不推荐第二种</span></span><br><span class="line"><span class="type">List</span> <span class="variable">list</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ArrayList</span>()</span><br><span class="line"><span class="type">ArrayList</span> <span class="variable">list</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ArrayList</span>()</span><br><span class="line"><span class="comment">// 体现了java语言的多态性</span></span><br><span class="line"><span class="type">List</span> <span class="variable">list</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ArrayList</span>();</span><br></pre></td></tr></table></figure>

<ul>
<li><p>java是面向对象编程，面向对象一个重要的原则就是“依赖倒置原则”。依赖抽象（接口），而非具体（实现类）</p>
<p>List是接口，ArrayList是实现类，<code>它允许list可以轻松地在接口的不同实现之间切换</code></p>
</li>
<li><p>List的实现类包括List，Vector，LinkedList , Stack等等，使用<code>List list = new ArrayList()</code>将来如果需要改成线程安全的<code>Vector</code>，只需要直接把<code>ArrayList</code>改成<code>Vector</code>就行了。即<code>List list = new Vector()</code>这种方法实现解耦合，大大提高代码使用的灵活性和通用性，并且在暴露公共接口的时候尤其有用</p>
</li>
</ul>
<h3 id="Map"><a href="#Map" class="headerlink" title="Map"></a>Map</h3><p>Map是java中的接口，Map.Entry是Map的一个内部接口。常用方法：<code>keySet()</code> 和 <code>entrySet()</code></p>
<p>​		<strong>keySet()方法</strong>：返回值是Map中key值的集合</p>
<p>​		<strong>entrySet()方法</strong>：返回值是一个Set集合，此集合的类型为<code>Map.Entry</code>，它是Map声明的一个内部接口，此接口为泛型，定义为<code>Entry&lt;K,V&gt;</code>。它表示									 Map中的一个实体即一个<code>key-value</code>对。接口中有 <code>getKey()</code>，<code>getValue()</code>等方法</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">Map&lt;String, String&gt; map = <span class="keyword">new</span> <span class="title class_">HashMap</span>&lt;String, String&gt;();</span><br><span class="line">map.put(“key1”, “value1”);</span><br><span class="line">map.put(“key2”, “value2”);</span><br><span class="line">map.put(“key3”, “value3”);</span><br></pre></td></tr></table></figure>

<blockquote>
<p>第一种：普遍使用，二次取值。即通过 <code>Map.keySet()</code> 遍历key和value</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span> (String key : map.keySet()) &#123;</span><br><span class="line">	System.out.println(<span class="string">&quot;key= &quot;</span>+ key + <span class="string">&quot; and value= &quot;</span> + map.get(key));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<blockquote>
<p>第二种：通过 <code>Map.entrySet</code> 使用 <code>iterator</code> 遍历key和value</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">Iterator&lt;Map.Entry&lt;String, String&gt;&gt; it = map.entrySet().iterator();</span><br><span class="line"><span class="keyword">while</span> (it.hasNext()) &#123;</span><br><span class="line">    Map.Entry&lt;String, String&gt; entry = it.next();</span><br><span class="line">    System.out.println(<span class="string">&quot;key= &quot;</span> + entry.getKey() + <span class="string">&quot; and value= &quot;</span> + entry.getValue());</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<blockquote>
<p>第三种：推荐，尤其是容量大时，即通过 <code>Map.entrySet</code> 遍历key和value</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span> (Map.Entry&lt;String, String&gt; entry : map.entrySet()) &#123;</span><br><span class="line">	System.out.println(<span class="string">&quot;key= &quot;</span> + entry.getKey() + <span class="string">&quot; and value= &quot;</span> + entry.getValue());</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<blockquote>
<p> 第四种：通过Map.values()遍历所有的value，但不能遍历key</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span> (String v : map.values()) &#123;</span><br><span class="line">	System.out.println(<span class="string">&quot;value= &quot;</span> + v);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h3 id="Iterator和Iterable的区别"><a href="#Iterator和Iterable的区别" class="headerlink" title="Iterator和Iterable的区别"></a>Iterator和Iterable的区别</h3><blockquote>
<p>为什么Collection接口要继承于Iterable接口，而不是Iterator接口？</p>
</blockquote>
<ul>
<li><p>在jdk 1.5以后，引入了 <code>Iterable</code> ，使用 <code>foreach</code> 语句必须使用 <code>Iterable</code> 类</p>
</li>
<li><p>Java设计者让 Collection 继承于 <code>Iterable</code> 而不是 <code>Iterator</code> 接口</p>
<p><code>Iterable</code> 的子类是 Collection，Collection 的子类是List，Set等，这些是数据结构或者说放数据的地方</p>
<p><code>Iterator</code> 是定义了迭代逻辑的对象，让迭代逻辑和数据结构分离开来，这样的好处是可以在一种数据结构上实现多种迭代逻辑</p>
</li>
<li><p>更重要的一点是：每一次调用 <code>Iterable</code> 的 <code>Iterator()</code> 方法，都会返回一个从头开始的 <code>Iterator</code> 对象，各个 <code>Iterator</code> 对象之间不会相互干扰，这样保证了可以同时对一个数据结构进行多个遍历。这是因为每个循环都是用了独立的迭代器 <code>Iterator</code> 对象</p>
</li>
</ul>
<img src= "" data-lazy-src="https://cdn.jsdelivr.net/gh/cxz206015/For-PicGo@main/img/895904-20160509230146280-371593991.png" alt="img" style="zoom: 33%;" />



<hr>
<h2 id="Stream流"><a href="#Stream流" class="headerlink" title="Stream流"></a>Stream流</h2><ul>
<li>根据条件映射</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">list.stream().map(条件).collect(Collectors.toList());</span><br></pre></td></tr></table></figure>

<ul>
<li>根据条件遍历</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">list.stream().foreach(条件).collect(Collectors.toList());</span><br></pre></td></tr></table></figure>

<ul>
<li>根据条件分组</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">list.stream().collect(Collectors.groupingBy(条件));</span><br></pre></td></tr></table></figure>

<ul>
<li>根据条件排序</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">list.stream().sorted(条件).collect(Collectors.toList());</span><br></pre></td></tr></table></figure>

<ul>
<li>根据条件筛选、</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">list.stream().filter(条件).collect(Collectors.toList());</span><br></pre></td></tr></table></figure>

<ul>
<li>根据条件缩减</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">list.stream().reduce(条件)</span><br></pre></td></tr></table></figure>

<ul>
<li>根据条件比较大小</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">list.stream().max(Comparator.comparing(条件));</span><br><span class="line">list.stream().min(Comparator.comparing(条件));</span><br></pre></td></tr></table></figure>

<ul>
<li>查询集合第一个元素</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">list.stream().filter(条件).findFirst();</span><br><span class="line">list.stream().filter(条件).findAny();</span><br></pre></td></tr></table></figure>

<ul>
<li>查询集合元素数量</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">list.stream().filter(条件).count();</span><br></pre></td></tr></table></figure>

<ul>
<li>跳过前m个数据，</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">list.stream().skip(m).collect(Collectors.toList());</span><br></pre></td></tr></table></figure>

<ul>
<li>限制获得前n个数据</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">list.stream().limit(n).collect(Collectors.toList());</span><br></pre></td></tr></table></figure>

<ul>
<li>去重</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">list.stream().distinct().collect(Collectors.toList());</span><br></pre></td></tr></table></figure>

<ul>
<li>合并，去重</li>
</ul>
<blockquote>
<p>合并的stream类型必须相同,只能两两合并</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Stream.concat(stream1, stream2).distinct().collect(Collectors.toList());</span><br></pre></td></tr></table></figure>

<ul>
<li>加字符  “,”</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">stream().map().collect(Collectors.joining(<span class="string">&quot;,&quot;</span>));</span><br></pre></td></tr></table></figure>




<hr>
<h2 id="语法"><a href="#语法" class="headerlink" title="语法"></a>语法</h2><h3 id="正则表达式"><a href="#正则表达式" class="headerlink" title="正则表达式"></a>正则表达式</h3><ul>
<li>匹配：使用<code>matches()</code>方法来判断一个字符串是否与正则表达式匹配。例如：</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">String</span> <span class="variable">regex</span> <span class="operator">=</span> <span class="string">&quot;a*b&quot;</span>;</span><br><span class="line"><span class="type">String</span> <span class="variable">input</span> <span class="operator">=</span> <span class="string">&quot;aab&quot;</span>;</span><br><span class="line"><span class="type">boolean</span> <span class="variable">isMatch</span> <span class="operator">=</span> input.matches(regex);<span class="comment">//true</span></span><br></pre></td></tr></table></figure>

<ul>
<li>搜索与替换：使用<code>Pattern</code>和<code>Matcher</code>类来进行搜索和替换操作。例如：</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">String</span> <span class="variable">regex</span> <span class="operator">=</span> <span class="string">&quot;\\bcat\\b&quot;</span>;</span><br><span class="line"><span class="type">String</span> <span class="variable">input</span> <span class="operator">=</span> <span class="string">&quot;I have a cat and a dog.&quot;</span>;</span><br><span class="line"><span class="type">Pattern</span> <span class="variable">pattern</span> <span class="operator">=</span> Pattern.compile(regex);</span><br><span class="line"><span class="type">Matcher</span> <span class="variable">matcher</span> <span class="operator">=</span> pattern.matcher(input);</span><br><span class="line"><span class="type">boolean</span> <span class="variable">found</span> <span class="operator">=</span> matcher.find(); <span class="comment">// 搜索匹配项  true</span></span><br><span class="line"><span class="type">String</span> <span class="variable">replacedInput</span> <span class="operator">=</span> matcher.replaceAll(<span class="string">&quot;dog&quot;</span>); <span class="comment">// 替换匹配项 I have a dog and a dog.</span></span><br></pre></td></tr></table></figure>

<ul>
<li>分割字符串：使用<code>split()</code>方法来根据正则表达式将字符串分割成数组。例如：</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">String</span> <span class="variable">regex</span> <span class="operator">=</span> <span class="string">&quot;\\s+&quot;</span>; <span class="comment">// 表示一个或多个空格字符</span></span><br><span class="line"><span class="type">String</span> <span class="variable">input</span> <span class="operator">=</span> <span class="string">&quot;Hello     World&quot;</span>;</span><br><span class="line">String[] parts = input.split(regex); <span class="comment">//[&quot;Hello&quot;,&quot;World&quot;]</span></span><br></pre></td></tr></table></figure>

<ul>
<li>提取内容：使用分组（Grouping）来提取正则表达式中的特定部分。例如：</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">String</span> <span class="variable">regex</span> <span class="operator">=</span> <span class="string">&quot;(\\d&#123;4&#125;)-(\\d&#123;2&#125;)-(\\d&#123;2&#125;)&quot;</span>; <span class="comment">// 匹配日期格式（YYYY-MM-DD）</span></span><br><span class="line"><span class="type">String</span> <span class="variable">input</span> <span class="operator">=</span> <span class="string">&quot;Today is 2021-09-30&quot;</span>;</span><br><span class="line"><span class="type">Pattern</span> <span class="variable">pattern</span> <span class="operator">=</span> Pattern.compile(regex);</span><br><span class="line"><span class="type">Matcher</span> <span class="variable">matcher</span> <span class="operator">=</span> pattern.matcher(input);</span><br><span class="line"><span class="keyword">if</span> (matcher.find()) &#123;</span><br><span class="line">    <span class="type">String</span> <span class="variable">year</span> <span class="operator">=</span> matcher.group(<span class="number">1</span>); <span class="comment">// &quot;2021&quot;</span></span><br><span class="line">    <span class="type">String</span> <span class="variable">month</span> <span class="operator">=</span> matcher.group(<span class="number">2</span>); <span class="comment">// &quot;09&quot;</span></span><br><span class="line">    <span class="type">String</span> <span class="variable">day</span> <span class="operator">=</span> matcher.group(<span class="number">3</span>); <span class="comment">// &quot;30&quot;</span></span><br><span class="line">    <span class="type">String</span> <span class="variable">group</span> <span class="operator">=</span> matcher,group();<span class="comment">// &quot;2021-09-30&quot;</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<ul>
<li>Java中的反斜杠 <code>\</code> 在字符串中需要进行转义，因此正则表达式中的反斜杠需要使用两个反斜杠 <code>\\</code> 进行表示。</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">*	:匹配前一个元素零次或多次。</span><br><span class="line">.	:匹配任意单个字符（除了换行符 \n）。</span><br><span class="line">+	:匹配前一个元素一次或多次。</span><br><span class="line">?	:匹配前一个元素零次或一次。</span><br><span class="line">\b	:当它是由单词边界包围时才进行匹配 如上例</span><br><span class="line">\s	:用于匹配任意连续的空白字符。包括空格、制表符和换行符</span><br><span class="line">\d*	:匹配任意数量的数字字符（<span class="number">0</span> 次或多次）。</span><br><span class="line">\.	:匹配实际的点号字符。</span><br><span class="line">\d+	:匹配至少一个数字字符。</span><br><span class="line">\?	:匹配实际的问号字符。</span><br></pre></td></tr></table></figure>



<h3 id="字符串处理"><a href="#字符串处理" class="headerlink" title="字符串处理"></a>字符串处理</h3><ul>
<li>将字符串转成无 [] 的字符串</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">StringUtils.strip(collect.toString(), <span class="string">&quot;[]&quot;</span>)</span><br></pre></td></tr></table></figure>

<ul>
<li>数字和字母转换<ul>
<li>For inputString “A”错误</li>
<li>字符串截取操作</li>
</ul>
</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//Intege.parseInt(&quot;A&quot;)是不能被直接转化成数字的，会报错</span></span><br><span class="line"><span class="comment">//正确做法是将&quot;A&quot;转化成&#x27;A&#x27;,然后直接强制类型转换就行</span></span><br><span class="line"><span class="type">String</span> <span class="variable">code</span> <span class="operator">=</span> <span class="string">&quot;A&quot;</span>;</span><br><span class="line"><span class="type">int</span> <span class="variable">a1</span> <span class="operator">=</span> (<span class="type">int</span>)<span class="string">&#x27;A&#x27;</span></span><br><span class="line"><span class="type">int</span> <span class="variable">a2</span> <span class="operator">=</span> (<span class="type">int</span>)code.toUpperCase().charAt(<span class="number">0</span>)</span><br></pre></td></tr></table></figure>



<h3 id="转换对象"><a href="#转换对象" class="headerlink" title="转换对象"></a>转换对象</h3><ul>
<li>实体对象</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">BeanUtils.copyProperties(item,voItem);</span><br></pre></td></tr></table></figure>

<ul>
<li><code>list</code></li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// list1&lt;a&gt;   	</span></span><br><span class="line"><span class="comment">// list2&lt;b&gt;</span></span><br><span class="line">BeanUtils.copytoList(list1,list2);</span><br><span class="line">list2&lt;b&gt; = BeanUtils.copytoList(list1,b.class);</span><br></pre></td></tr></table></figure>



<h3 id="遍历"><a href="#遍历" class="headerlink" title="遍历"></a>遍历</h3><ul>
<li><code>foreach()</code>增强for循环</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span>(Vo vo : list)&#123;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<ul>
<li><code>stream.map</code></li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">list.stream().map((item)-&gt;&#123;</span><br><span class="line">	<span class="keyword">return</span> item;</span><br><span class="line">&#125;).collect(Collectors.toList());</span><br></pre></td></tr></table></figure>

<ul>
<li><code>list.foreach()</code> 和 <code>list.stream.foreach()</code></li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">list.forEach(item-&gt;&#123;</span><br><span class="line">&#125;);</span><br><span class="line"><span class="comment">//使用流处理</span></span><br><span class="line">lsit.stream.foreach(item-&gt;&#123;    </span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<ul>
<li>迭代器 <code>iterator</code></li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">Iterator&lt;xxx&gt; iterator = xxx.iterator();</span><br><span class="line"><span class="keyword">while</span> (iterator.hasNext()) &#123;</span><br><span class="line">    <span class="type">xxx</span> <span class="variable">xxx</span> <span class="operator">=</span> iterator.next();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h3 id="运算符"><a href="#运算符" class="headerlink" title="运算符"></a>运算符</h3><ul>
<li>自增运算符</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">1</span>;</span><br><span class="line"><span class="type">int</span> <span class="variable">j</span> <span class="operator">=</span> ++i + i++ + ++i + ++i + i++;</span><br><span class="line">System.out.println(j);<span class="comment">//18</span></span><br></pre></td></tr></table></figure>

<ul>
<li>逻辑运算符</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">HelloWorld</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="comment">//长路与  无论第一个表达式的值是true或者false,第二个的值，都会被运算</span></span><br><span class="line">        <span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">2</span>;</span><br><span class="line">        System.out.println( i== <span class="number">1</span> &amp; i++ ==<span class="number">2</span>  ); <span class="comment">//无论如何i++都会被执行，所以i的值变成了3</span></span><br><span class="line">        System.out.println(i);         </span><br><span class="line">        <span class="comment">//短路与 只要第一个表达式的值是false的，第二个表达式的值，就不需要进行运算了</span></span><br><span class="line">        <span class="type">int</span> <span class="variable">j</span> <span class="operator">=</span> <span class="number">2</span>;</span><br><span class="line">        System.out.println( j== <span class="number">1</span> &amp;&amp; j++ ==<span class="number">2</span>  );  <span class="comment">//因为j==1返回false,所以右边的j++就没有执行了，所以j的值，还是2</span></span><br><span class="line">        System.out.println(j);              </span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<hr>
<h2 id="Swagger"><a href="#Swagger" class="headerlink" title="Swagger"></a>Swagger</h2><blockquote>
<p>Api注解不是Spring自带的，他是swagger里面的，代码编写的时候需要在pom文件中引入相关swagger的依赖.</p>
</blockquote>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>io.springfox<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>springfox-swagger2<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>2.2.2<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>io.springfox<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>springfox-swagger-ui<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>2.2.2<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h3 id="常用注解"><a href="#常用注解" class="headerlink" title="常用注解"></a>常用注解</h3><ul>
<li><p>@Api：用在请求的类上，表示对类的说明。</p>
<ul>
<li>tags&#x3D;”说明该类的作用，可以在UI界面上看到的注解”，</li>
<li>value&#x3D;”该参数没什么意义，在UI界面上也看到，所以不需要配置”</li>
</ul>
</li>
<li><p>@ApiOperation：用在请求的方法上，说明方法的用途、作用。</p>
<ul>
<li>value &#x3D; “接口说明”，</li>
<li>httpMethod &#x3D; “接口请求方式”,</li>
<li>response &#x3D;“接口返回参数类型”, </li>
<li>notes &#x3D; “接口发布说明”；</li>
</ul>
</li>
<li><p>@ApiResponses：用在请求的方法上，表示一组响应</p>
<ul>
<li>@ApiResponse：用在@ApiResponses中，一般用于表达一个错误或正确的响应信息<ul>
<li>code：数字，例如400</li>
<li>message：信息，例如”请求参数没填好”</li>
<li>response：抛出异常的类</li>
</ul>
</li>
</ul>
</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@ApiResponses(&#123;</span></span><br><span class="line"><span class="meta">        @ApiResponse(code = 0, message = &quot;请求成功&quot;),</span></span><br><span class="line"><span class="meta">        @ApiResponse(code = 1, message = &quot;请求失败&quot;)</span></span><br><span class="line"><span class="meta">&#125;)</span></span><br></pre></td></tr></table></figure>

<ul>
<li><p>@ApiModelProperty：用在属性上，描述响应类的属性</p>
<ul>
<li>value-字段说明；</li>
<li>name-重写属性名字；</li>
<li>dataType-重写属性类型；</li>
<li>required-是否必填；</li>
<li>example-举例说明；</li>
<li>hidden-隐藏</li>
</ul>
</li>
<li><p>@ApiImplicitParams：用在请求的方法上，表示一组参数说明</p>
<ul>
<li>@ApiImplicitParam：用在@ApiImplicitParams注解中，指定一个请求参数的各个方面<ul>
<li>name：参数名；value：参数的汉字说明、解释；required：参数是否必须传</li>
<li>paramType：参数放在哪个地方</li>
<li>header –&gt; 请求参数的获取：@RequestHeader</li>
<li>query –&gt; 请求参数的获取：@RequestParam</li>
<li>path（用于restful接口）–&gt; 请求参数的获取：@PathVariable</li>
<li>body（不常用）</li>
<li>form（不常用）</li>
<li>dataType：参数类型，默认String，其它值dataType&#x3D;”Integer”</li>
<li>defaultValue：参数的默认值</li>
</ul>
</li>
</ul>
</li>
<li><p>@ApiModel：用于响应类上，表示一个返回响应数据的信息。这种一般用在post创建的时候，使用@RequestBody这样的场景，请求参数无法使用@ApiImplicitParam注解进行描述的时候</p>
</li>
</ul>
<hr>
<h2 id="hutool"><a href="#hutool" class="headerlink" title="hutool"></a>hutool</h2><h3 id="ObjectUtil的-isNull和-isEmpty"><a href="#ObjectUtil的-isNull和-isEmpty" class="headerlink" title="ObjectUtil的 isNull和 isEmpty"></a>ObjectUtil的 isNull和 isEmpty</h3><p><code>isNull(Object obj)</code>方法：</p>
<ul>
<li>该方法用于判断对象是否为 <code>null</code>。</li>
<li>如果传入的对象 <code>obj</code> 是 <code>null</code> 或者等于 <code>null</code>（通过调用 <code>equals</code> 方法进行判断），则返回 <code>true</code>，否则返回 <code>false</code>。</li>
<li>这个方法只关注对象是否为 <code>null</code>，不考虑对象的具体内容。</li>
</ul>
<p><code>isEmpty(Object obj)</code>方法：</p>
<ul>
<li>该方法用于判断对象是否为空。</li>
<li>如果传入的对象 <code>obj</code> 是 <code>null</code>，则返回 <code>true</code>。</li>
<li>如果传入的对象是 <code>CharSequence</code>（如字符串）、<code>Map</code>（如Map集合）、<code>Iterable</code>（如List、Set等可迭代对象）或<code>Iterator</code>（迭代器），则会调用对应的工具类方法来判断对象是否为空。比如，如果是字符串类型，则使用 <code>StrUtil.isEmpty</code> 方法来判断字符串是否为空。</li>
<li>如果传入的对象是数组类型，则使用 <code>ArrayUtil.isEmpty</code> 方法来判断数组是否为空。</li>
<li>如果传入的对象不属于上述类型，那么返回 <code>false</code>，表示对象不为空。</li>
</ul>
<blockquote>
<p>注意：<code>isEmpty() </code>方法会针对不同类型的对象调用相应的工具类方法来判断对象是否为空；<code>isNull()</code> 方法只关注对象是否为 null</p>
</blockquote>
<hr>
<h2 id="Jsoup"><a href="#Jsoup" class="headerlink" title="Jsoup"></a>Jsoup</h2><p><a target="_blank" rel="noopener" href="https://jsoup.org/">Jsoup官方文档</a></p>
<h3 id="解析HTML"><a href="#解析HTML" class="headerlink" title="解析HTML"></a>解析HTML</h3><ul>
<li><p><code>Jsoup.parse(String html)</code>: 将HTML字符串解析成一个Document对象。</p>
</li>
<li><p><code>Jsoup.parse(File in, String charsetName)</code>: 从文件中解析HTML文档。</p>
</li>
<li><p><code>Jsoup.parse(URL url, int timeoutMillis)</code>: 从URL中解析HTML文档。</p>
<p>遍历和选择元素：</p>
</li>
<li><p><code>getElementsByTag(String tagName)</code>: 选择指定标签名的元素，返回一个Elements对象。</p>
</li>
<li><p><code>getElementById(String id)</code>: 选择具有指定id属性的元素，返回一个Element对象。</p>
</li>
<li><p><code>getElementsByClass(String className)</code>: 选择具有指定CSS类名的元素，返回一个Elements对象。</p>
</li>
<li><p><code>Document.select(String cssQuery)</code>: 使用CSS选择器选择元素，返回一个Elements对象。</p>
</li>
<li><p><code>Element.select(String cssQuery)</code>: 在当前元素的子元素中使用CSS选择器选择元素，返回一个Elements对象。</p>
</li>
<li><p><code>Elements.first()</code>: 返回Elements集合中的第一个元素。</p>
</li>
<li><p><code>Elements.last()</code>: 返回Elements集合中的最后一个元素。</p>
</li>
<li><p><code>Elements.get(int index)</code>: 返回Elements集合中指定索引位置的元素。</p>
</li>
<li><p><code>Elements.hasAttr(String attributeKey)</code>: 选择具有指定属性的元素。</p>
</li>
<li><p><code>Elements.not(String cssQuery)</code>: 排除符合指定选择器的元素。</p>
</li>
<li><p><code>Element.traverse(NodeVisitor nodeVisitor)</code>: 使用自定义的NodeVisitor遍历元素及其子元素。</p>
</li>
<li><p><code>Element.wrap(String html)</code>: 将元素用指定的HTML包装起来。</p>
</li>
<li><p><code>Element.unwrap()</code>: 移除元素的父元素，保留元素本身。</p>
</li>
</ul>
<h3 id="过滤元素"><a href="#过滤元素" class="headerlink" title="过滤元素"></a>过滤元素</h3><ul>
<li><code>Elements.filter(NodeFilter nodeFilter)</code>: 使用自定义的NodeFilter过滤元素。</li>
</ul>
<h3 id="操作元素"><a href="#操作元素" class="headerlink" title="操作元素"></a>操作元素</h3><ul>
<li><code>Element.tagName()</code>: 获取元素的标签名。</li>
<li><code>Element.text()</code>: 获取元素的文本内容。</li>
<li><code>Element.html()</code>: 获取元素的HTML内容。</li>
<li><code>Element.attr(String attributeKey)</code>: 获取元素指定属性的值。</li>
<li><code>Element.attr(String attributeKey, String attributeValue)</code>: 设置元素指定属性的值。</li>
<li><code>Element.append(String html)</code>: 在元素的末尾添加HTML内容。</li>
<li><code>Element.prepend(String html)</code>: 在元素的开头添加HTML内容。</li>
<li><code>Element.after(String html)</code>: 在元素之后插入HTML内容。</li>
<li><code>Element.before(String html)</code>: 在元素之前插入HTML内容。</li>
<li><code>Element.remove()</code>: 移除元素。</li>
</ul>
<h3 id="提取和修改HTML文档结构"><a href="#提取和修改HTML文档结构" class="headerlink" title="提取和修改HTML文档结构"></a>提取和修改HTML文档结构</h3><ul>
<li><code>Document.body()</code>: 获取HTML文档的<code>&lt;body&gt;</code>元素。</li>
<li><code>Element.parent()</code>: 获取元素的父元素。</li>
<li><code>Element.children()</code>: 获取元素的直接子元素。</li>
<li><code>Element.clone()</code>: 克隆元素及其子元素。</li>
<li><code>Element.replaceWith(Node replacement)</code>: 用指定的节点替换元素。</li>
<li><code>Element.replaceWith(String html)</code>: 用指定的HTML内容替换元素。</li>
</ul>
<h3 id="操作CSS类"><a href="#操作CSS类" class="headerlink" title="操作CSS类"></a>操作CSS类</h3><ul>
<li><code>Element.hasClass(String className)</code>: 检查元素是否具有指定的CSS类。</li>
<li><code>Element.addClass(String className)</code>: 为元素添加CSS类。</li>
<li><code>Element.removeClass(String className)</code>: 从元素中移除指定的CSS类。</li>
</ul>
<h3 id="处理表单数据"><a href="#处理表单数据" class="headerlink" title="处理表单数据"></a>处理表单数据</h3><ul>
<li><code>FormElement.formData()</code>: 获取表单元素中的所有表单数据。</li>
</ul>
<h3 id="获取和设置表单数据"><a href="#获取和设置表单数据" class="headerlink" title="获取和设置表单数据"></a>获取和设置表单数据</h3><ul>
<li><code>Element.val()</code>: 获取或设置元素的值。</li>
<li><code>Element.val(String value)</code>: 设置元素的值。</li>
</ul>
<h3 id="处理相对和绝对URL"><a href="#处理相对和绝对URL" class="headerlink" title="处理相对和绝对URL"></a>处理相对和绝对URL</h3><ul>
<li><code>Element.absUrl(String attributeKey)</code>: 获取元素指定属性的绝对URL。</li>
</ul>
<h3 id="处理特殊字符和编码"><a href="#处理特殊字符和编码" class="headerlink" title="处理特殊字符和编码"></a>处理特殊字符和编码</h3><ul>
<li><code>Entities.escape(String string)</code>: 对HTML文本进行转义。</li>
<li><code>Entities.unescape(String string)</code>: 解码HTML文本中的特殊字符。</li>
</ul>
<hr>
<h2 id="Java数据脱敏"><a href="#Java数据脱敏" class="headerlink" title="Java数据脱敏"></a>Java数据脱敏</h2><h3 id="①-SQL数据脱敏实现"><a href="#①-SQL数据脱敏实现" class="headerlink" title="① SQL数据脱敏实现"></a>① SQL数据脱敏实现</h3><p><a target="_blank" rel="noopener" href="https://www.jb51.net/article/213589.htm">MYSQL(电话号码,身份证)数据脱敏的实现</a></p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- CONCAT()、LEFT()和RIGHT()字符串函数组合使用，请看下面具体实现</span></span><br><span class="line"><span class="comment">-- CONCAT(str1,str2,…)：返回结果为连接参数产生的字符串</span></span><br><span class="line"><span class="comment">-- LEFT(str,len)：返回从字符串str 开始的len 最左字符</span></span><br><span class="line"><span class="comment">-- RIGHT(str,len)：从字符串str 开始，返回最右len 字符</span></span><br><span class="line"><span class="comment">-- 电话号码脱敏sql：</span></span><br><span class="line"><span class="keyword">SELECT</span> mobilePhone <span class="keyword">AS</span> 脱敏前电话号码,CONCAT(<span class="keyword">LEFT</span>(mobilePhone,<span class="number">3</span>), <span class="string">&#x27;********&#x27;</span> ) <span class="keyword">AS</span> 脱敏后电话号码 <span class="keyword">FROM</span> t_s_user</span><br><span class="line"><span class="comment">-- 身份证号码脱敏sql:</span></span><br><span class="line"><span class="keyword">SELECT</span> idcard <span class="keyword">AS</span> 未脱敏身份证, CONCAT(<span class="keyword">LEFT</span>(idcard,<span class="number">3</span>), <span class="string">&#x27;****&#x27;</span> ,<span class="keyword">RIGHT</span>(idcard,<span class="number">4</span>)) <span class="keyword">AS</span> 脱敏后身份证号 <span class="keyword">FROM</span> t_s_user</span><br></pre></td></tr></table></figure>

<h3 id="②-JAVA数据脱敏"><a href="#②-JAVA数据脱敏" class="headerlink" title="② JAVA数据脱敏"></a>② JAVA数据脱敏</h3><p>可参考：<a target="_blank" rel="noopener" href="https://gitee.com/strong_sea/sensitive-plus?_from=gitee_search">sensitive-plus</a></p>
<p>数据脱敏插件，目前支持地址脱敏、银行卡号脱敏、中文姓名脱敏、固话脱敏、身份证号脱敏、手机号脱敏、密码脱敏 一个是正则脱敏、另外一个根据显示长度脱敏，默认是正则脱敏，可以根据自己的需要配置自己的规则。</p>
<h3 id="③-mybatis-mate-sensitive-jackson"><a href="#③-mybatis-mate-sensitive-jackson" class="headerlink" title="③ mybatis-mate-sensitive-jackson"></a>③ mybatis-mate-sensitive-jackson</h3><p><a target="_blank" rel="noopener" href="https://gitee.com/baomidou/mybatis-mate-examples/tree/master/mybatis-mate-sensitive-jackson">mybatis-mate-sensitive-jackson</a></p>
<p>根据定义的策略类型，对数据进行脱敏，当然策略可以自定义。</p>
<hr>
<h2 id="BeanUtils-copyProperties的坑"><a href="#BeanUtils-copyProperties的坑" class="headerlink" title="BeanUtils.copyProperties的坑"></a>BeanUtils.copyProperties的坑</h2><p>我们日常开发中，经常涉及到<code>DO、DTO、VO</code>对象属性拷贝赋值，很容易想到<code>org.springframework.beans.BeanUtils</code>的<code>copyProperties </code>。它会自动通过反射机制获取源对象和目标对象的属性，<strong>并将对应的属性值进行复制</strong>。可以减少手动编写属性复制代码的工作量，提高代码的可读性和维护性。</p>
<p><img src= "" data-lazy-src="https://cdn.jsdelivr.net/gh/cxz206015/For-PicGo@main/img/640.png" alt="img"></p>
<h3 id="第1个坑：类型不匹配"><a href="#第1个坑：类型不匹配" class="headerlink" title="第1个坑：类型不匹配"></a>第1个坑：类型不匹配</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Data</span>  </span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SourceBean</span> &#123;  </span><br><span class="line">    <span class="keyword">private</span> Long age;  </span><br><span class="line">&#125;    </span><br><span class="line"><span class="meta">@Data</span>  </span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">TargetBean</span> &#123;  </span><br><span class="line">    <span class="keyword">private</span> String age;  </span><br><span class="line">&#125;   </span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Test</span> &#123;    </span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;  </span><br><span class="line">        <span class="type">SourceBean</span> <span class="variable">source</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">SourceBean</span>();  </span><br><span class="line">        source.setAge(<span class="number">25L</span>);   </span><br><span class="line">        <span class="type">TargetBean</span> <span class="variable">target</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">TargetBean</span>();  </span><br><span class="line">        BeanUtils.copyProperties(source, target);    </span><br><span class="line">        System.out.println(target.getAge());  <span class="comment">//拷贝赋值失败，输出null  </span></span><br><span class="line">    &#125;  </span><br><span class="line">&#125;  </span><br></pre></td></tr></table></figure>

<p>源对象<code>SourceBean</code>的<code>age</code>属性是<code>Long</code>类型，目标对象<code>TargetBean</code>的<code>age</code>属性是<code>String</code>类型。由于类型不匹配，<code>BeanUtils.copyProperties</code>赋值失败</p>
<h3 id="第2个坑：浅拷贝"><a href="#第2个坑：浅拷贝" class="headerlink" title="第2个坑：浅拷贝"></a>第2个坑：浅拷贝</h3><p>什么是深拷贝？什么是浅拷贝？</p>
<ul>
<li><p>浅拷贝是指创建一个新对象，该对象的属性值与原始对象相同，但对于引用类型的属性，仍然共享相同的引用。</p>
<blockquote>
<p>浅拷贝只复制对象及其引用，而不复制引用指向的对象本身</p>
</blockquote>
</li>
<li><p>深拷贝是指创建一个新对象，该对象的属性值与原始对象相同，包括引用类型的属性。</p>
<blockquote>
<p>深拷贝会递归复制引用对象，创建全新的对象，以确保拷贝后的对象与原始对象完全独立</p>
</blockquote>
</li>
</ul>
<p><img src= "" data-lazy-src="https://cdn.jsdelivr.net/gh/cxz206015/For-PicGo@main/img/641.png" alt="图片"></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Address</span> &#123;  </span><br><span class="line">    <span class="keyword">private</span> String city;</span><br><span class="line">&#125;  </span><br><span class="line">  </span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Person</span> &#123;  </span><br><span class="line">    <span class="keyword">private</span> String name;  </span><br><span class="line">    <span class="keyword">private</span> Address address;  </span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="type">Person</span> <span class="variable">sourcePerson</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Person</span>();  </span><br><span class="line">sourcePerson.setName(<span class="string">&quot;John&quot;</span>);  </span><br><span class="line"><span class="type">Address</span> <span class="variable">address</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Address</span>();  </span><br><span class="line">address.setCity(<span class="string">&quot;New York&quot;</span>);  </span><br><span class="line">sourcePerson.setAddress(address);  </span><br><span class="line"><span class="type">Person</span> <span class="variable">targetPerson</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Person</span>();  </span><br><span class="line">BeanUtils.copyProperties(sourcePerson, targetPerson);  </span><br><span class="line"></span><br><span class="line">sourcePerson.getAddress().setCity(<span class="string">&quot;London&quot;</span>);  </span><br><span class="line">  </span><br><span class="line">System.out.println(targetPerson.getAddress().getCity());  <span class="comment">// 输出为 &quot;London&quot;  </span></span><br></pre></td></tr></table></figure>

<p>源对象<code>Person</code>的属性<code>address</code>是引用类型。使用<code>BeanUtils.copyProperties</code>方法进行属性复制时，只复制了引用。即目标对象<code>targetPerson</code>的 <code>address</code> 属性引用和源对象 <code>sourcePerson</code> 的 <code>address</code> 属性引用指向同一个对象。因此，当修改源对象的<code>address</code>对象时，目标对象的<code>address</code>对象也会被修改。</p>
<h3 id="第3个坑：属性名称不一致"><a href="#第3个坑：属性名称不一致" class="headerlink" title="第3个坑：属性名称不一致"></a>第3个坑：属性名称不一致</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SourceBean</span> &#123;  </span><br><span class="line">    <span class="keyword">private</span> String username;  </span><br><span class="line">&#125;    </span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">TargetBean</span> &#123;  </span><br><span class="line">    <span class="keyword">private</span> String userName;  </span><br><span class="line">&#125;    </span><br><span class="line"><span class="type">SourceBean</span> <span class="variable">source</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">SourceBean</span>();  </span><br><span class="line">source.setUsername(<span class="string">&quot;捡田螺的小男孩&quot;</span>);  </span><br><span class="line"></span><br><span class="line"><span class="type">TargetBean</span> <span class="variable">target</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">TargetBean</span>();  </span><br><span class="line">BeanUtils.copyProperties(source, target);  </span><br><span class="line"></span><br><span class="line">System.out.println(target.getUserName());   <span class="comment">// 输出为 null  </span></span><br></pre></td></tr></table></figure>

<p>源对象<code>SourceBean</code> 的属性名称是<code>username</code>，而目标对象<code>TargetBean</code>的属性名称也是<code>userName</code>。但是，两个 <code>username</code>，一个N是大写，一个n是小写，即<strong>属性名称不一致</strong>，<code>BeanUtils.copyProperties</code>方法无法自动映射这些属性（无法忽略大小写自动匹配），因此目标对象的<code>userName</code>属性值为<code>null</code>。</p>
<blockquote>
<p> 日常开发注意：大小写不一致，差一两个字母等等</p>
</blockquote>
<h3 id="第4个坑：Null-值覆盖"><a href="#第4个坑：Null-值覆盖" class="headerlink" title="第4个坑：Null 值覆盖"></a>第4个坑：Null 值覆盖</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Data</span>  </span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SourceBean</span> &#123;   </span><br><span class="line">    <span class="keyword">private</span> String name;  </span><br><span class="line">    <span class="keyword">private</span> String address;    </span><br><span class="line">&#125;    </span><br><span class="line"><span class="meta">@Data</span>  </span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">TargetBean</span> &#123;    </span><br><span class="line">    <span class="keyword">private</span> String name;  </span><br><span class="line">    <span class="keyword">private</span> String address;  </span><br><span class="line">&#125;  </span><br><span class="line">  </span><br><span class="line"><span class="type">SourceBean</span> <span class="variable">source</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">SourceBean</span>();  </span><br><span class="line">source.setName(<span class="string">&quot;John&quot;</span>);  </span><br><span class="line">source.setAddress(<span class="literal">null</span>);  </span><br><span class="line">  </span><br><span class="line"><span class="type">TargetBean</span> <span class="variable">target</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">TargetBean</span>();  </span><br><span class="line">target.setAddress(<span class="string">&quot;田螺address&quot;</span>);  </span><br><span class="line">BeanUtils.copyProperties(source, target);  </span><br><span class="line">  </span><br><span class="line">System.out.println(target.getAddress());  <span class="comment">// 输出为 null  </span></span><br></pre></td></tr></table></figure>

<p>源对象 <code>SourceBean </code>的 address 属性值为 null。默认情况下，<code>BeanUtils.copyProperties</code> 方法会将源对象中的 null 值属性覆盖到目标对象中。因此，目标对象的 address 属性值也为 null。</p>
<p>如果不希望 null 值覆盖目标对象中的属性，可以用 <code>BeanUtils.copyProperties</code> 方法的重载方法，并传入一个自定义的 <code>ConvertUtilsBean</code> 实例来进行配置。</p>
<h3 id="第5个坑：注意引入的包"><a href="#第5个坑：注意引入的包" class="headerlink" title="第5个坑：注意引入的包"></a>第5个坑：注意引入的包</h3><p><code>BeanUtils.copyProperties</code>其实有两个包，分别是<code>spring、apache</code>。这两个包，是有点不一样的：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//org.springframework.beans.BeanUtils(源对象在左边，目标对象在右边)  </span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">copyProperties</span><span class="params">(Object source, Object target)</span> <span class="keyword">throws</span> BeansException   </span><br><span class="line"><span class="comment">//org.apache.commons.beanutils.BeanUtils（源对象在右边，目标对象在左边）  </span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">copyProperties</span><span class="params">(Object dest, Object orig)</span> <span class="keyword">throws</span> IllegalAccessException, InvocationTargetException  </span><br></pre></td></tr></table></figure>

<p>注意自己引入的哪个<code>BeanUtils</code>，写对应参数位置。</p>
<h3 id="第6个坑：Boolean类型数据-is属性开头的坑"><a href="#第6个坑：Boolean类型数据-is属性开头的坑" class="headerlink" title="第6个坑：Boolean类型数据+is属性开头的坑"></a>第6个坑：Boolean类型数据+is属性开头的坑</h3><p>把<code>SourceBean和TargetBean</code>中的都有个属性<code>isTianLuo</code>,它们的数据类型保持不变,但是一个为基本类型<code>boolean</code>，一个为包装类型<code>Boolean</code></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Data</span>  </span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SourceBean</span> &#123;  </span><br><span class="line">    <span class="keyword">private</span> <span class="type">boolean</span> isTianLuo;  </span><br><span class="line">&#125;  </span><br><span class="line"><span class="meta">@Data</span>  </span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">TargetBean</span> &#123;  </span><br><span class="line">    <span class="keyword">private</span> Boolean isTianLuo;  </span><br><span class="line">&#125;  </span><br></pre></td></tr></table></figure>

<p>跑测试用里的时候，发现赋值不上：这是因为当属性类型为<code>boolean</code>时，属性名以<code>is</code>开头,属性名会去掉前面的<code>is</code>，因此源对象和目标对象属性对不上。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">SourceBean</span> <span class="variable">source</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">SourceBean</span>();  </span><br><span class="line">source.setTianLuo(<span class="literal">true</span>);  </span><br><span class="line">  </span><br><span class="line"><span class="type">TargetBean</span> <span class="variable">target</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">TargetBean</span>();  </span><br><span class="line">BeanUtils.copyProperties(source, target);  </span><br><span class="line">System.out.println(target.getIsTianLuo()); <span class="comment">// 输出为 null  </span></span><br></pre></td></tr></table></figure>

<h3 id="第7个坑：查找不到字段引用"><a href="#第7个坑：查找不到字段引用" class="headerlink" title="第7个坑：查找不到字段引用"></a>第7个坑：查找不到字段引用</h3><p>在某些开发场景呢，如果我们要修改某个字段的赋值，我们可能会全文搜索它的所有<code>set</code>方法，看哪些地方引用到。但是如果使用<code>BeanUtils.copyProperties</code>就不知道是否引用到对应的ste方法啦<strong>，</strong>即查找不到字段引用，这就可能导致你会漏掉修改对应的字段。</p>
<p><img src= "" data-lazy-src="https://cdn.jsdelivr.net/gh/cxz206015/For-PicGo@main/img/644.png" alt="图片"></p>
<p><img src= "" data-lazy-src="https://cdn.jsdelivr.net/gh/cxz206015/For-PicGo@main/img/643.png" alt="图片"></p>
<h3 id="第8个坑：不同内部类，即使相同属性，也是赋值失败"><a href="#第8个坑：不同内部类，即使相同属性，也是赋值失败" class="headerlink" title="第8个坑：不同内部类，即使相同属性，也是赋值失败"></a>第8个坑：不同内部类，即使相同属性，也是赋值失败</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Data</span>  </span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">CopySource</span> &#123;   </span><br><span class="line">    <span class="keyword">public</span> String outerName;  </span><br><span class="line">    <span class="keyword">public</span> CopySource.InnerClass innerClass;    </span><br><span class="line">    <span class="meta">@Data</span>  </span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">class</span> <span class="title class_">InnerClass</span> &#123;  </span><br><span class="line">        <span class="keyword">public</span> String InnerName;  </span><br><span class="line">    &#125;  </span><br><span class="line">&#125;    </span><br><span class="line"><span class="meta">@Data</span>  </span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">CopyTarget</span> &#123;  </span><br><span class="line">    <span class="keyword">public</span> String outerName;  </span><br><span class="line">    <span class="keyword">public</span> CopyTarget.InnerClass innerClass;   </span><br><span class="line">    <span class="meta">@Data</span>  </span><br><span class="line">   <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">class</span> <span class="title class_">InnerClass</span> &#123;  </span><br><span class="line">        <span class="keyword">public</span> String InnerName;  </span><br><span class="line">    &#125;  </span><br><span class="line">&#125;  </span><br><span class="line">  </span><br><span class="line"><span class="type">CopySource</span> <span class="variable">test1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">CopySource</span>();  </span><br><span class="line">test1.outerName = <span class="string">&quot;outTianluo&quot;</span>;  </span><br><span class="line">  </span><br><span class="line">CopySource.<span class="type">InnerClass</span> <span class="variable">innerClass</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">CopySource</span>.InnerClass();  </span><br><span class="line">innerClass.InnerName = <span class="string">&quot;innerTianLuo&quot;</span>;  </span><br><span class="line">test1.innerClass = innerClass;  </span><br><span class="line">  </span><br><span class="line">System.out.println(test1);  </span><br><span class="line"><span class="type">CopyTarget</span> <span class="variable">test2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">CopyTarget</span>();  </span><br><span class="line">BeanUtils.copyProperties(test1, test2);  </span><br><span class="line">  </span><br><span class="line">System.out.println(test2);  <span class="comment">//输出CopyTarget(outerName=outTianluo, innerClass=null)  </span></span><br></pre></td></tr></table></figure>

<p><code>CopySource</code>和<code>CopyTarget</code>各自存在一个内部类<code>InnerClass</code>，虽然这个内部类属性也相同，类名也相同，但是在不同的类中，因此<code>Spring</code>会认为属性不同,不会<code>Copy</code>。如果要复制成功，可以让他们指向同一个内部类。</p>
<h3 id="第9个坑：bean对应的属性，没有getter和setter方法，赋值失败"><a href="#第9个坑：bean对应的属性，没有getter和setter方法，赋值失败" class="headerlink" title="第9个坑：bean对应的属性，没有getter和setter方法，赋值失败"></a>第9个坑：bean对应的属性，没有getter和setter方法，赋值失败</h3><p><code>BeanUtils.copyProperties</code>要拷贝属性值成功，需要对应的<code>bean</code>有<code>getter和setter</code>方法。因为它是用反射拿到set和get方法再去拿属性值和设置属性值的。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Data</span>  </span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SourceBean</span> &#123;  </span><br><span class="line">    <span class="keyword">private</span> String value;  </span><br><span class="line">&#125;  </span><br><span class="line"><span class="meta">@Getter</span>   <span class="comment">//没有对应的setter方法  </span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">TargetBean</span> &#123;  </span><br><span class="line">    <span class="keyword">private</span> String value;  </span><br><span class="line">&#125;  </span><br><span class="line">  </span><br><span class="line"><span class="type">SourceBean</span> <span class="variable">source</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">SourceBean</span>();  </span><br><span class="line">source.setValue(<span class="string">&quot;捡田螺的小男孩&quot;</span>);  </span><br><span class="line">  </span><br><span class="line"><span class="type">TargetBean</span> <span class="variable">target</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">TargetBean</span>();  </span><br><span class="line">BeanUtils.copyProperties(source, target);  </span><br><span class="line">System.out.println(target.getValue()); <span class="comment">//输出null   </span></span><br></pre></td></tr></table></figure>

<h3 id="第10个坑：BeanUtils-copyProperties-泛型"><a href="#第10个坑：BeanUtils-copyProperties-泛型" class="headerlink" title="第10个坑：BeanUtils.copyProperties + 泛型"></a>第10个坑：BeanUtils.copyProperties + 泛型</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Data</span>  </span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">CopySource</span> &#123;    </span><br><span class="line">    <span class="keyword">public</span> String outerName;  </span><br><span class="line">    <span class="keyword">public</span> List&lt;CopySource.InnerClass&gt; clazz;    </span><br><span class="line">    <span class="meta">@Data</span>  </span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">class</span> <span class="title class_">InnerClass</span> &#123;  </span><br><span class="line">        <span class="keyword">public</span> String InnerName;  </span><br><span class="line">    &#125;  </span><br><span class="line">&#125;    </span><br><span class="line"><span class="meta">@ToString</span>  </span><br><span class="line"><span class="meta">@Data</span>  </span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">CopyTarget</span> &#123;  </span><br><span class="line">    <span class="keyword">public</span> String outerName;  </span><br><span class="line">    <span class="keyword">public</span> List&lt;CopyTarget.InnerClass&gt; clazz;    </span><br><span class="line">    <span class="meta">@Data</span>  </span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">class</span> <span class="title class_">InnerClass</span> &#123;  </span><br><span class="line">        <span class="keyword">public</span> String InnerName;  </span><br><span class="line">    &#125;  </span><br><span class="line">&#125;  </span><br><span class="line">  </span><br><span class="line"><span class="type">CopySource</span> <span class="variable">test1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">CopySource</span>();  </span><br><span class="line">test1.outerName = <span class="string">&quot;outTianluo&quot;</span>;  </span><br><span class="line">  </span><br><span class="line">CopySource.<span class="type">InnerClass</span> <span class="variable">innerClass</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">CopySource</span>.InnerClass();  </span><br><span class="line">innerClass.InnerName = <span class="string">&quot;innerTianLuo&quot;</span>;  </span><br><span class="line">  </span><br><span class="line">List&lt;CopySource.InnerClass&gt; clazz = <span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;&gt;();  </span><br><span class="line">clazz.add(innerClass);  </span><br><span class="line">test1.setClazz(clazz);  </span><br><span class="line">  </span><br><span class="line">System.out.println(test1);  </span><br><span class="line"><span class="type">CopyTarget</span> <span class="variable">test2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">CopyTarget</span>();  </span><br><span class="line">BeanUtils.copyProperties(test1, test2);  </span><br><span class="line">  </span><br><span class="line">System.out.println(test2);  <span class="comment">//输出CopyTarget(outerName=outTianluo, clazz=null)  </span></span><br></pre></td></tr></table></figure>

<p><code>BeanUtils.copyProperties</code>方法拷贝包含泛型属性的对象<code>clazz</code>。<code>CopyTarget</code>和<code>CopySource</code>的泛型属性类型不匹配，因此拷贝赋值失败。</p>
<h3 id="第11个坑：性能问题"><a href="#第11个坑：性能问题" class="headerlink" title="第11个坑：性能问题"></a>第11个坑：性能问题</h3><p>由于这些<code>BeanUtils</code>类都是采用反射机制实现的，对程序的效率也会有影响。<code>demo</code>对比：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">SourceBean</span> <span class="variable">sourceBean</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">SourceBean</span>();  </span><br><span class="line">sourceBean.setName(<span class="string">&quot;tianLuoBoy&quot;</span>);  </span><br><span class="line"><span class="type">TargetBean</span> <span class="variable">target</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">TargetBean</span>();  </span><br><span class="line">  </span><br><span class="line"><span class="type">long</span> <span class="variable">beginTime</span> <span class="operator">=</span> System.currentTimeMillis();  </span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; <span class="number">100000</span>; i++) &#123;  <span class="comment">//循环10万次  </span></span><br><span class="line">      target.setName(sourceBean.getName());  </span><br><span class="line">&#125;  </span><br><span class="line">System.out.println(<span class="string">&quot;common setter time:&quot;</span> + (System.currentTimeMillis() - beginTime));  </span><br><span class="line">  </span><br><span class="line"><span class="type">long</span> <span class="variable">beginTime1</span> <span class="operator">=</span> System.currentTimeMillis();  </span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; <span class="number">100000</span>; i++) &#123;  <span class="comment">//循环10万次  </span></span><br><span class="line">    BeanUtils.copyProperties(sourceBean, target);  </span><br><span class="line">&#125;  </span><br><span class="line">System.out.println(<span class="string">&quot;bean copy time:&quot;</span> + (System.currentTimeMillis() - beginTime1));  </span><br><span class="line">  </span><br><span class="line"><span class="comment">//输出  </span></span><br><span class="line">common setter time:<span class="number">3</span>  </span><br><span class="line">bean copy time:<span class="number">331</span>  </span><br></pre></td></tr></table></figure>

<p>可以发现，简单的<code>setter</code>和<code>BeanUtils.copyProperties</code>对比，性能差距非常大。因此，慎用<code>BeanUtils.copyProperties</code></p>
<h3 id="替换BeanUtils-copyProperties的方案"><a href="#替换BeanUtils-copyProperties的方案" class="headerlink" title="替换BeanUtils.copyProperties的方案"></a>替换BeanUtils.copyProperties的方案</h3><p><strong>第一种</strong>，那就是使用原始的<code>setter和getter</code>方法。</p>
<blockquote>
<p>使用手动的setter方法进行属性赋值。这种方法可能需要编写更多的代码，但是可以提供更细粒度的控制，并且在性能方面通常比BeanUtils.copyProperties更高效。</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">Target</span> <span class="variable">target</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Target</span>();  </span><br><span class="line">target.setName(source.getName());  </span><br><span class="line">target.setAge(source.getAge());  </span><br></pre></td></tr></table></figure>

<p>如果实在对象<code>bean</code>的属性比较多的话，可以使用插件<code>GenerateAllSetter</code>，它可以一键生成对象的<code>set</code>方法，挺方便的。</p>
<p><strong>第二种方案</strong>，使用映射工具库，如<code>MapStruct、ModelMapper</code>等，它们可以自动生成属性映射的代码。这些工具库可以减少手动编写setter方法的工作量，并提供更好的性能。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Mapper</span>  </span><br><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">SourceTargetMapper</span> &#123;  </span><br><span class="line">    <span class="type">SourceTargetMapper</span> <span class="variable">INSTANCE</span> <span class="operator">=</span> Mappers.getMapper(SourceTargetMapper.class);  </span><br><span class="line">    <span class="meta">@Mapping(source = &quot;name&quot;, target = &quot;name&quot;)</span>  </span><br><span class="line">    <span class="meta">@Mapping(source = &quot;age&quot;, target = &quot;age&quot;)</span>  </span><br><span class="line">    Target <span class="title function_">mapToTarget</span><span class="params">(Source source)</span>;  </span><br><span class="line">&#125;  </span><br><span class="line"><span class="type">Target</span> <span class="variable">target</span> <span class="operator">=</span> SourceTargetMapper.INSTANCE.mapToTarget(source);</span><br></pre></td></tr></table></figure>



<hr>
<h2 id="导出文件相关"><a href="#导出文件相关" class="headerlink" title="导出文件相关"></a>导出文件相关</h2><h3 id="递归输出文件夹里全部文件名"><a href="#递归输出文件夹里全部文件名" class="headerlink" title="递归输出文件夹里全部文件名"></a>递归输出文件夹里全部文件名</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">listFilesRecursively</span><span class="params">(File folder)</span> &#123;</span><br><span class="line">    File[] contents = folder.listFiles();</span><br><span class="line">    <span class="keyword">if</span> (contents != <span class="literal">null</span>) &#123;</span><br><span class="line">        <span class="keyword">for</span> (File item : contents) &#123;</span><br><span class="line">            <span class="keyword">if</span> (item.isFile()) &#123;</span><br><span class="line">                System.out.println(item.getAbsolutePath());</span><br><span class="line">            &#125; <span class="keyword">else</span> <span class="keyword">if</span> (item.isDirectory()) &#123;</span><br><span class="line">                listFilesRecursively(item);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">    <span class="comment">// 替换为你想要遍历的文件夹路径</span></span><br><span class="line">    <span class="type">String</span> <span class="variable">folderPath</span> <span class="operator">=</span> <span class="string">&quot;F:\\Typora\\touchfish\\9.PDF books&quot;</span>;</span><br><span class="line">    <span class="type">File</span> <span class="variable">folder</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">File</span>(folderPath);</span><br><span class="line">    listFilesRecursively(folder);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="导出为docx或流文件"><a href="#导出为docx或流文件" class="headerlink" title="导出为docx或流文件"></a>导出为docx或流文件</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//导出到指定路径的docx文件</span></span><br><span class="line"><span class="type">File</span> <span class="variable">file</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">File</span>(templatePath + paperName + <span class="string">&quot;.docx&quot;</span>);</span><br><span class="line"><span class="keyword">try</span> (</span><br><span class="line">    <span class="type">InputStream</span> <span class="variable">is</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">FileInputStream</span>(file);</span><br><span class="line">    <span class="type">ServletOutputStream</span> <span class="variable">out</span> <span class="operator">=</span> response.getOutputStream();</span><br><span class="line">) &#123;</span><br><span class="line">    <span class="type">byte</span>[] buffer = <span class="keyword">new</span> <span class="title class_">byte</span>[<span class="number">1024</span>];</span><br><span class="line">    <span class="type">int</span> len;</span><br><span class="line">    <span class="keyword">while</span> ((len = is.read(buffer)) != -<span class="number">1</span>) &#123;</span><br><span class="line">    out.write(buffer, <span class="number">0</span>, len);</span><br><span class="line">	&#125;</span><br><span class="line">&#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">	e.printStackTrace();</span><br><span class="line">&#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">	FileUtils.del(file);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 导出为流文件：</span></span><br><span class="line"><span class="comment">// 1.直接返回response的二进制流，这种在response里的流不能携带其他任何信息</span></span><br><span class="line"><span class="comment">// response.setContentType(&quot;application/octet-stream&quot;);</span></span><br><span class="line"><span class="comment">// response.setHeader(&quot;Content-disposition&quot;, &quot;attachment;filename=paper.docx&quot;);</span></span><br><span class="line"><span class="comment">//2.返回带信息的流,可以封装一个实体包括信息和转为base64格式的二进制流文件</span></span><br><span class="line"><span class="keyword">try</span> (</span><br><span class="line">    <span class="type">ByteArrayOutputStream</span> <span class="variable">os</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ByteArrayOutputStream</span>();</span><br><span class="line">) &#123;</span><br><span class="line">    <span class="comment">//用Base64转换二级制流导出错误数据，用于前端下载</span></span><br><span class="line">	ExcelUtil.exportTemplate(errorStudentList,<span class="string">&quot;excel/exportStudentTemplate.xlsx&quot;</span>, os);</span><br><span class="line">    <span class="type">String</span> <span class="variable">encodeToString</span> <span class="operator">=</span> Base64.getEncoder().encodeToString(os.toByteArray());</span><br><span class="line">&#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">    <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">RuntimeException</span>(<span class="string">&quot;导入异常&quot;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="动态导出表头"><a href="#动态导出表头" class="headerlink" title="动态导出表头"></a>动态导出表头</h3><p><img src= "" data-lazy-src="https://cdn.jsdelivr.net/gh/cxz206015/For-PicGo@main/img/image-20230918113035142.png" alt="image-20230918113035142"></p>
<hr>
<h2 id="调用微信接口"><a href="#调用微信接口" class="headerlink" title="调用微信接口"></a>调用微信接口</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">WechatTest</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">String</span> <span class="variable">APP_ID</span> <span class="operator">=</span> <span class="string">&quot;xxx&quot;</span>;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">String</span> <span class="variable">APP_SECRET</span> <span class="operator">=</span> <span class="string">&quot;xxx&quot;</span>;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">String</span> <span class="variable">GROUP_NAME</span> <span class="operator">=</span> <span class="string">&quot;森林之父游戏群&quot;</span>;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">String</span> <span class="variable">NEW_GROUP_NAME</span> <span class="operator">=</span> <span class="string">&quot;森林之子游戏群&quot;</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="comment">// 获取访问凭证</span></span><br><span class="line">            <span class="type">String</span> <span class="variable">accessToken</span> <span class="operator">=</span> getAccessToken();</span><br><span class="line">            <span class="keyword">if</span> (accessToken == <span class="literal">null</span>) &#123;</span><br><span class="line">                System.out.println(<span class="string">&quot;Failed to get access token.&quot;</span>);</span><br><span class="line">                <span class="keyword">return</span>;</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            <span class="comment">// 获取微信群列表</span></span><br><span class="line">            <span class="type">String</span> <span class="variable">groupListJson</span> <span class="operator">=</span> getWeChatGroupList(accessToken);</span><br><span class="line">            <span class="keyword">if</span> (groupListJson == <span class="literal">null</span>) &#123;</span><br><span class="line">                System.out.println(<span class="string">&quot;Failed to get WeChat group list.&quot;</span>);</span><br><span class="line">                <span class="keyword">return</span>;</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            <span class="comment">// 根据群名称查找群ID</span></span><br><span class="line">            <span class="type">String</span> <span class="variable">groupId</span> <span class="operator">=</span> findGroupIdByGroupName(groupListJson, GROUP_NAME);</span><br><span class="line">            <span class="keyword">if</span> (groupId == <span class="literal">null</span>) &#123;</span><br><span class="line">                System.out.println(<span class="string">&quot;Target group not found.&quot;</span>);</span><br><span class="line">                <span class="keyword">return</span>;</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            <span class="comment">// 修改群名称</span></span><br><span class="line">            <span class="type">boolean</span> <span class="variable">success</span> <span class="operator">=</span> updateGroupName(accessToken, groupId, NEW_GROUP_NAME);</span><br><span class="line">            <span class="keyword">if</span> (success) &#123;</span><br><span class="line">                System.out.println(<span class="string">&quot;Group name updated successfully.&quot;</span>);</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                System.out.println(<span class="string">&quot;Failed to update group name.&quot;</span>);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> String <span class="title function_">getAccessToken</span><span class="params">()</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">        <span class="type">String</span> <span class="variable">url</span> <span class="operator">=</span> <span class="string">&quot;https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&amp;appid=&quot;</span></span><br><span class="line">                + APP_ID + <span class="string">&quot;&amp;secret=&quot;</span> + APP_SECRET;</span><br><span class="line"></span><br><span class="line">        <span class="type">HttpURLConnection</span> <span class="variable">connection</span> <span class="operator">=</span> (HttpURLConnection) <span class="keyword">new</span> <span class="title class_">URL</span>(url).openConnection();</span><br><span class="line">        connection.setRequestMethod(<span class="string">&quot;GET&quot;</span>);</span><br><span class="line">        connection.setConnectTimeout(<span class="number">5000</span>);</span><br><span class="line">        connection.setReadTimeout(<span class="number">5000</span>);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (connection.getResponseCode() == HttpURLConnection.HTTP_OK) &#123;</span><br><span class="line">            <span class="type">BufferedReader</span> <span class="variable">reader</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">BufferedReader</span>(<span class="keyword">new</span> <span class="title class_">InputStreamReader</span>(connection.getInputStream()));</span><br><span class="line">            String line;</span><br><span class="line">            <span class="type">StringBuilder</span> <span class="variable">response</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">StringBuilder</span>();</span><br><span class="line">            <span class="keyword">while</span> ((line = reader.readLine()) != <span class="literal">null</span>) &#123;</span><br><span class="line">                response.append(line);</span><br><span class="line">            &#125;</span><br><span class="line">            reader.close();</span><br><span class="line"></span><br><span class="line">            <span class="comment">// 解析返回的 JSON 数据，获取访问凭证</span></span><br><span class="line">            <span class="comment">// 这里仅作示例，假设返回的 JSON 数据中有一个字段为 &quot;access_token&quot;</span></span><br><span class="line">            <span class="comment">// 实际情况中，请根据微信返回的 JSON 数据结构来解析访问凭证</span></span><br><span class="line">            <span class="type">int</span> <span class="variable">startIndex</span> <span class="operator">=</span> response.indexOf(<span class="string">&quot;\&quot;access_token\&quot;:\&quot;&quot;</span>) + <span class="number">16</span>;</span><br><span class="line">            <span class="type">int</span> <span class="variable">endIndex</span> <span class="operator">=</span> response.indexOf(<span class="string">&quot;\&quot;,\&quot;expires_in\&quot;&quot;</span>);</span><br><span class="line">            <span class="keyword">return</span> response.substring(startIndex, endIndex);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;Failed to get access token. Response code: &quot;</span> + connection.getResponseCode());</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">null</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> String <span class="title function_">getWeChatGroupList</span><span class="params">(String accessToken)</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">        <span class="type">String</span> <span class="variable">url</span> <span class="operator">=</span> <span class="string">&quot;https://api.weixin.qq.com/cgi-bin/groups/get?access_token=&quot;</span> + accessToken;</span><br><span class="line"></span><br><span class="line">        <span class="type">HttpURLConnection</span> <span class="variable">connection</span> <span class="operator">=</span> (HttpURLConnection) <span class="keyword">new</span> <span class="title class_">URL</span>(url).openConnection();</span><br><span class="line">        connection.setRequestMethod(<span class="string">&quot;GET&quot;</span>);</span><br><span class="line">        connection.setConnectTimeout(<span class="number">5000</span>);</span><br><span class="line">        connection.setReadTimeout(<span class="number">5000</span>);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (connection.getResponseCode() == HttpURLConnection.HTTP_OK) &#123;</span><br><span class="line">            <span class="type">BufferedReader</span> <span class="variable">reader</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">BufferedReader</span>(<span class="keyword">new</span> <span class="title class_">InputStreamReader</span>(connection.getInputStream()));</span><br><span class="line">            String line;</span><br><span class="line">            <span class="type">StringBuilder</span> <span class="variable">response</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">StringBuilder</span>();</span><br><span class="line">            <span class="keyword">while</span> ((line = reader.readLine()) != <span class="literal">null</span>) &#123;</span><br><span class="line">                response.append(line);</span><br><span class="line">            &#125;</span><br><span class="line">            reader.close();</span><br><span class="line"></span><br><span class="line">            <span class="keyword">return</span> response.toString();</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;Failed to get WeChat group list. Response code: &quot;</span> + connection.getResponseCode());</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">null</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> String <span class="title function_">findGroupIdByGroupName</span><span class="params">(String groupListJson, String groupName)</span> &#123;</span><br><span class="line">        <span class="comment">// 解析微信群列表的 JSON 数据，查找目标群的群ID</span></span><br><span class="line">        <span class="comment">// 这里仅作示例，假设返回的 JSON 数据中有一个字段为 &quot;groups&quot;，其中包含群列表</span></span><br><span class="line">        <span class="comment">// 实际情况中，请根据微信返回的 JSON 数据结构来解析群列表和群ID</span></span><br><span class="line"></span><br><span class="line">        <span class="type">String</span> <span class="variable">groupId</span> <span class="operator">=</span> <span class="string">&quot;YOUR_GROUP_ID&quot;</span>;</span><br><span class="line">        <span class="keyword">return</span> groupId;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="type">boolean</span> <span class="title function_">updateGroupName</span><span class="params">(String accessToken, String groupId, String newGroupName)</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">        <span class="type">String</span> <span class="variable">url</span> <span class="operator">=</span> <span class="string">&quot;https://api.weixin.qq.com/cgi-bin/groups/update?access_token=&quot;</span> + accessToken;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 构建修改群名称的请求体</span></span><br><span class="line">        <span class="type">String</span> <span class="variable">requestBody</span> <span class="operator">=</span> String.format(<span class="string">&quot;&#123;\&quot;group\&quot;:&#123;\&quot;id\&quot;:%s,\&quot;name\&quot;:\&quot;%s\&quot;&#125;&#125;&quot;</span>,</span><br><span class="line">                groupId, URLEncoder.encode(newGroupName, <span class="string">&quot;UTF-8&quot;</span>));</span><br><span class="line"></span><br><span class="line">        <span class="type">HttpURLConnection</span> <span class="variable">connection</span> <span class="operator">=</span> (HttpURLConnection) <span class="keyword">new</span> <span class="title class_">URL</span>(url).openConnection();</span><br><span class="line">        connection.setRequestMethod(<span class="string">&quot;POST&quot;</span>);</span><br><span class="line">        connection.setConnectTimeout(<span class="number">5000</span>);</span><br><span class="line">        connection.setReadTimeout(<span class="number">5000</span>);</span><br><span class="line">        connection.setDoOutput(<span class="literal">true</span>);</span><br><span class="line">        connection.getOutputStream().write(requestBody.getBytes(<span class="string">&quot;UTF-8&quot;</span>));</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (connection.getResponseCode() == HttpURLConnection.HTTP_OK) &#123;</span><br><span class="line">            <span class="type">BufferedReader</span> <span class="variable">reader</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">BufferedReader</span>(<span class="keyword">new</span> <span class="title class_">InputStreamReader</span>(connection.getInputStream()));</span><br><span class="line">            String line;</span><br><span class="line">            <span class="type">StringBuilder</span> <span class="variable">response</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">StringBuilder</span>();</span><br><span class="line">            <span class="keyword">while</span> ((line = reader.readLine()) != <span class="literal">null</span>) &#123;</span><br><span class="line">                response.append(line);</span><br><span class="line">            &#125;</span><br><span class="line">            reader.close();</span><br><span class="line"></span><br><span class="line">            <span class="comment">// 解析返回的 JSON 数据，检查修改是否成功</span></span><br><span class="line">            <span class="comment">// 这里仅作示例，假设返回的 JSON 数据中有一个字段为 &quot;errcode&quot;，为 0 表示修改成功</span></span><br><span class="line">            <span class="comment">// 实际情况中，请根据微信返回的 JSON 数据结构来解析修改结果</span></span><br><span class="line">            <span class="type">int</span> <span class="variable">errCode</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line">            <span class="keyword">if</span> (errCode == <span class="number">0</span>) &#123;</span><br><span class="line">                <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                System.out.println(<span class="string">&quot;Failed to update group name. Error code: &quot;</span> + errCode);</span><br><span class="line">                <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;Failed to update group name. Response code: &quot;</span> + connection.getResponseCode());</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>





<hr>
<h2 id="面试"><a href="#面试" class="headerlink" title="面试"></a>面试</h2><h3 id="项目中有没有用到AOP？"><a href="#项目中有没有用到AOP？" class="headerlink" title="项目中有没有用到AOP？"></a>项目中有没有用到AOP？</h3><blockquote>
<p>当时在后台管理系统中，使用了aop的环绕通知+切点表达式，这个表达式就是要找到要记录日志的方法，然后通过环绕通知的参数获取请求方法的参数，比如类信息、注解、请求方式的等，获取到这些参数以后，保存到数据库。</p>
</blockquote>
</article><div class="post-copyright"><div class="post-copyright__author"><span class="post-copyright-meta"><i class="fas fa-circle-user fa-fw"></i>文章作者: </span><span class="post-copyright-info"><a href="https://cxzde.cn">耶比大熊</a></span></div><div class="post-copyright__type"><span class="post-copyright-meta"><i class="fas fa-square-arrow-up-right fa-fw"></i>文章链接: </span><span class="post-copyright-info"><a href="https://cxzde.cn/2024/04/01/note-java/">https://cxzde.cn/2024/04/01/note-java/</a></span></div><div class="post-copyright__notice"><span class="post-copyright-meta"><i class="fas fa-circle-exclamation fa-fw"></i>版权声明: </span><span class="post-copyright-info">本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" target="_blank">CC BY-NC-SA 4.0</a> 许可协议。转载请注明来自 <a href="https://cxzde.cn" target="_blank">耶比大熊</a>！</span></div></div><div class="tag_share"><div class="post-meta__tag-list"></div><div class="post_share"><div class="social-share" data-image="https://tuchuang.voooe.cn/images/2024/04/07/background2.jpg" data-sites="facebook,twitter,wechat,weibo,qq"></div><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/butterfly-extsrc@1.1.3/sharejs/dist/css/share.min.css" media="print" onload="this.media='all'"><script src="https://cdn.jsdelivr.net/npm/butterfly-extsrc@1.1.3/sharejs/dist/js/social-share.min.js" defer></script></div></div><nav class="pagination-post" id="pagination"><div class="prev-post pull-full"><a href="/2024/04/02/note-git/" title="Git"><img class="cover" src= "" data-lazy-src="https://tuchuang.voooe.cn/images/2024/04/07/background4.jpg" onerror="onerror=null;src='/img/404.jpg'" alt="cover of previous post"><div class="pagination-info"><div class="label">上一篇</div><div class="prev_info">Git</div></div></a></div></nav></div><div class="aside-content" id="aside-content"><div class="card-widget card-info"><div class="is-center"><div class="avatar-img"><img src= "" data-lazy-src="/img/avatar.jpg" onerror="this.onerror=null;this.src='/img/friend_404.gif'" alt="avatar"/></div><div class="author-info__name">耶比大熊</div><div class="author-info__description">隐约雷鸣 阴霾天空 但盼风雨来 能留你在此</div></div><div class="card-info-data site-data is-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">10</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">0</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">0</div></a></div><a id="card-info-btn" href="https://cxzde.cn"><i></i><span>🚀异次元之旅🚀</span></a><div class="card-info-social-icons is-center"><a class="social-icon" href="https://github.com/cxz206015" target="_blank" title="Github"><i class="fab fa-github" style="color: #24292e;"></i></a><a class="social-icon" href="mailto:2324308799@qq.com" target="_blank" title="Email"><i class="fas fa-envelope" style="color: #4a7dbe;"></i></a><a class="social-icon" href="https://www.zhihu.com/people/ashbell" target="_blank" title="知乎"><i class="iconfont icon-zhihu-circle-fill"></i></a></div></div><div class="card-widget card-announcement"><div class="item-headline"><i class="fas fa-bullhorn fa-shake"></i><span>公告</span></div><div class="announcement_content"><div style="text-align:center;"><a target="_blank" rel="noopener" href="https://www.bilibili.com/bangumi/play/ep785525/?share_source=copy_web">节选自——《凡人修仙传》86集 文戏<br></a></span>吾幼时好棋 <br>名镇乡野 <br>人皆谓神童 <br>年岁稍长 遇一山野老道 <br>三天对弈 终得一胜 <br>老道愿赌服输 施展法术 <br>通天遁地 <br>吾顿生神往 <br>遂弃棋修道 <br>可惜吾天赋一般 <br>只求矜矜业业 苦心钻研 <br>不惜远家人 抛爱侣 <br>弃友人 漂泊四海 无所依绊 <br>几经险境 <br>半生贫苦 <br>老来方有定所 <br>可惜 时日无多 <br>近来常思 <br>人生百年 蜉蝣一日 <br>长生于我何有哉 <br>不过又入樊笼尔 <br>不若二三好友 <br>弈棋饮酒 <br>良缘佳侣 人间携手 <br>风光百年 同归尘土 <br>但 <br>问道之心 <br>终归难改 <br>纵使蹉跎一生 <br>也要争那 一线天机 <br>只因幼时便知 <br>人生如棋 <br>落子 <br>无悔 <br></div></div><button></button></div><div class="sticky_layout"><div class="card-widget" id="card-toc"><div class="item-headline"><i class="fas fa-stream"></i><span>目录</span><span class="toc-percentage"></span></div><div class="toc-content"><ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%89%8D%E5%90%8E%E7%AB%AF%E4%BC%A0%E5%8F%82"><span class="toc-number">1.</span> <span class="toc-text">前后端传参</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%B8%89%E7%A7%8D%E4%BC%A0%E5%8F%82%E6%96%B9%E5%BC%8F"><span class="toc-number">1.1.</span> <span class="toc-text">三种传参方式</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#post%E5%92%8Cget%E8%AF%B7%E6%B1%82"><span class="toc-number">1.2.</span> <span class="toc-text">post和get请求</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#ajax%E8%AF%B7%E6%B1%82"><span class="toc-number">2.</span> <span class="toc-text">ajax请求</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#ajax%E8%AF%B7%E6%B1%82%E8%A7%84%E8%8C%83"><span class="toc-number">2.1.</span> <span class="toc-text">ajax请求规范</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%BC%A0%E5%8F%82%E9%97%AE%E9%A2%98"><span class="toc-number">2.2.</span> <span class="toc-text">传参问题</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%97%A5%E5%BF%97"><span class="toc-number">3.</span> <span class="toc-text">日志</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%97%A5%E5%BF%97%E6%A1%86%E6%9E%B6%E5%92%8C%E6%97%A5%E5%BF%97%E9%97%A8%E9%9D%A2"><span class="toc-number">3.1.</span> <span class="toc-text">日志框架和日志门面</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%97%A5%E5%BF%97%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8"><span class="toc-number">3.2.</span> <span class="toc-text">日志如何使用</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%BC%82%E5%B8%B8"><span class="toc-number">4.</span> <span class="toc-text">异常</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8B"><span class="toc-number">5.</span> <span class="toc-text">网络编程</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#Socket%E7%9A%84%E5%9F%BA%E6%9C%AC%E5%8E%9F%E7%90%86"><span class="toc-number">5.1.</span> <span class="toc-text">Socket的基本原理</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Socket%E7%9A%84%E5%85%B8%E5%9E%8B%E7%94%A8%E9%80%94"><span class="toc-number">5.2.</span> <span class="toc-text">Socket的典型用途</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%BD%BF%E7%94%A8%E6%B5%81%E7%A8%8B"><span class="toc-number">5.3.</span> <span class="toc-text">使用流程</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E9%9B%86%E5%90%88"><span class="toc-number">6.</span> <span class="toc-text">集合</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#List"><span class="toc-number">6.1.</span> <span class="toc-text">List</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Map"><span class="toc-number">6.2.</span> <span class="toc-text">Map</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Iterator%E5%92%8CIterable%E7%9A%84%E5%8C%BA%E5%88%AB"><span class="toc-number">6.3.</span> <span class="toc-text">Iterator和Iterable的区别</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Stream%E6%B5%81"><span class="toc-number">7.</span> <span class="toc-text">Stream流</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E8%AF%AD%E6%B3%95"><span class="toc-number">8.</span> <span class="toc-text">语法</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F"><span class="toc-number">8.1.</span> <span class="toc-text">正则表达式</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%A4%84%E7%90%86"><span class="toc-number">8.2.</span> <span class="toc-text">字符串处理</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E8%BD%AC%E6%8D%A2%E5%AF%B9%E8%B1%A1"><span class="toc-number">8.3.</span> <span class="toc-text">转换对象</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E9%81%8D%E5%8E%86"><span class="toc-number">8.4.</span> <span class="toc-text">遍历</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E8%BF%90%E7%AE%97%E7%AC%A6"><span class="toc-number">8.5.</span> <span class="toc-text">运算符</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Swagger"><span class="toc-number">9.</span> <span class="toc-text">Swagger</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%B8%B8%E7%94%A8%E6%B3%A8%E8%A7%A3"><span class="toc-number">9.1.</span> <span class="toc-text">常用注解</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#hutool"><span class="toc-number">10.</span> <span class="toc-text">hutool</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#ObjectUtil%E7%9A%84-isNull%E5%92%8C-isEmpty"><span class="toc-number">10.1.</span> <span class="toc-text">ObjectUtil的 isNull和 isEmpty</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Jsoup"><span class="toc-number">11.</span> <span class="toc-text">Jsoup</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E8%A7%A3%E6%9E%90HTML"><span class="toc-number">11.1.</span> <span class="toc-text">解析HTML</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E8%BF%87%E6%BB%A4%E5%85%83%E7%B4%A0"><span class="toc-number">11.2.</span> <span class="toc-text">过滤元素</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%93%8D%E4%BD%9C%E5%85%83%E7%B4%A0"><span class="toc-number">11.3.</span> <span class="toc-text">操作元素</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%8F%90%E5%8F%96%E5%92%8C%E4%BF%AE%E6%94%B9HTML%E6%96%87%E6%A1%A3%E7%BB%93%E6%9E%84"><span class="toc-number">11.4.</span> <span class="toc-text">提取和修改HTML文档结构</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%93%8D%E4%BD%9CCSS%E7%B1%BB"><span class="toc-number">11.5.</span> <span class="toc-text">操作CSS类</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%A4%84%E7%90%86%E8%A1%A8%E5%8D%95%E6%95%B0%E6%8D%AE"><span class="toc-number">11.6.</span> <span class="toc-text">处理表单数据</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E8%8E%B7%E5%8F%96%E5%92%8C%E8%AE%BE%E7%BD%AE%E8%A1%A8%E5%8D%95%E6%95%B0%E6%8D%AE"><span class="toc-number">11.7.</span> <span class="toc-text">获取和设置表单数据</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%A4%84%E7%90%86%E7%9B%B8%E5%AF%B9%E5%92%8C%E7%BB%9D%E5%AF%B9URL"><span class="toc-number">11.8.</span> <span class="toc-text">处理相对和绝对URL</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%A4%84%E7%90%86%E7%89%B9%E6%AE%8A%E5%AD%97%E7%AC%A6%E5%92%8C%E7%BC%96%E7%A0%81"><span class="toc-number">11.9.</span> <span class="toc-text">处理特殊字符和编码</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Java%E6%95%B0%E6%8D%AE%E8%84%B1%E6%95%8F"><span class="toc-number">12.</span> <span class="toc-text">Java数据脱敏</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E2%91%A0-SQL%E6%95%B0%E6%8D%AE%E8%84%B1%E6%95%8F%E5%AE%9E%E7%8E%B0"><span class="toc-number">12.1.</span> <span class="toc-text">① SQL数据脱敏实现</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E2%91%A1-JAVA%E6%95%B0%E6%8D%AE%E8%84%B1%E6%95%8F"><span class="toc-number">12.2.</span> <span class="toc-text">② JAVA数据脱敏</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E2%91%A2-mybatis-mate-sensitive-jackson"><span class="toc-number">12.3.</span> <span class="toc-text">③ mybatis-mate-sensitive-jackson</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#BeanUtils-copyProperties%E7%9A%84%E5%9D%91"><span class="toc-number">13.</span> <span class="toc-text">BeanUtils.copyProperties的坑</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E7%AC%AC1%E4%B8%AA%E5%9D%91%EF%BC%9A%E7%B1%BB%E5%9E%8B%E4%B8%8D%E5%8C%B9%E9%85%8D"><span class="toc-number">13.1.</span> <span class="toc-text">第1个坑：类型不匹配</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E7%AC%AC2%E4%B8%AA%E5%9D%91%EF%BC%9A%E6%B5%85%E6%8B%B7%E8%B4%9D"><span class="toc-number">13.2.</span> <span class="toc-text">第2个坑：浅拷贝</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E7%AC%AC3%E4%B8%AA%E5%9D%91%EF%BC%9A%E5%B1%9E%E6%80%A7%E5%90%8D%E7%A7%B0%E4%B8%8D%E4%B8%80%E8%87%B4"><span class="toc-number">13.3.</span> <span class="toc-text">第3个坑：属性名称不一致</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E7%AC%AC4%E4%B8%AA%E5%9D%91%EF%BC%9ANull-%E5%80%BC%E8%A6%86%E7%9B%96"><span class="toc-number">13.4.</span> <span class="toc-text">第4个坑：Null 值覆盖</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E7%AC%AC5%E4%B8%AA%E5%9D%91%EF%BC%9A%E6%B3%A8%E6%84%8F%E5%BC%95%E5%85%A5%E7%9A%84%E5%8C%85"><span class="toc-number">13.5.</span> <span class="toc-text">第5个坑：注意引入的包</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E7%AC%AC6%E4%B8%AA%E5%9D%91%EF%BC%9ABoolean%E7%B1%BB%E5%9E%8B%E6%95%B0%E6%8D%AE-is%E5%B1%9E%E6%80%A7%E5%BC%80%E5%A4%B4%E7%9A%84%E5%9D%91"><span class="toc-number">13.6.</span> <span class="toc-text">第6个坑：Boolean类型数据+is属性开头的坑</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E7%AC%AC7%E4%B8%AA%E5%9D%91%EF%BC%9A%E6%9F%A5%E6%89%BE%E4%B8%8D%E5%88%B0%E5%AD%97%E6%AE%B5%E5%BC%95%E7%94%A8"><span class="toc-number">13.7.</span> <span class="toc-text">第7个坑：查找不到字段引用</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E7%AC%AC8%E4%B8%AA%E5%9D%91%EF%BC%9A%E4%B8%8D%E5%90%8C%E5%86%85%E9%83%A8%E7%B1%BB%EF%BC%8C%E5%8D%B3%E4%BD%BF%E7%9B%B8%E5%90%8C%E5%B1%9E%E6%80%A7%EF%BC%8C%E4%B9%9F%E6%98%AF%E8%B5%8B%E5%80%BC%E5%A4%B1%E8%B4%A5"><span class="toc-number">13.8.</span> <span class="toc-text">第8个坑：不同内部类，即使相同属性，也是赋值失败</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E7%AC%AC9%E4%B8%AA%E5%9D%91%EF%BC%9Abean%E5%AF%B9%E5%BA%94%E7%9A%84%E5%B1%9E%E6%80%A7%EF%BC%8C%E6%B2%A1%E6%9C%89getter%E5%92%8Csetter%E6%96%B9%E6%B3%95%EF%BC%8C%E8%B5%8B%E5%80%BC%E5%A4%B1%E8%B4%A5"><span class="toc-number">13.9.</span> <span class="toc-text">第9个坑：bean对应的属性，没有getter和setter方法，赋值失败</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E7%AC%AC10%E4%B8%AA%E5%9D%91%EF%BC%9ABeanUtils-copyProperties-%E6%B3%9B%E5%9E%8B"><span class="toc-number">13.10.</span> <span class="toc-text">第10个坑：BeanUtils.copyProperties + 泛型</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E7%AC%AC11%E4%B8%AA%E5%9D%91%EF%BC%9A%E6%80%A7%E8%83%BD%E9%97%AE%E9%A2%98"><span class="toc-number">13.11.</span> <span class="toc-text">第11个坑：性能问题</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%9B%BF%E6%8D%A2BeanUtils-copyProperties%E7%9A%84%E6%96%B9%E6%A1%88"><span class="toc-number">13.12.</span> <span class="toc-text">替换BeanUtils.copyProperties的方案</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%AF%BC%E5%87%BA%E6%96%87%E4%BB%B6%E7%9B%B8%E5%85%B3"><span class="toc-number">14.</span> <span class="toc-text">导出文件相关</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E9%80%92%E5%BD%92%E8%BE%93%E5%87%BA%E6%96%87%E4%BB%B6%E5%A4%B9%E9%87%8C%E5%85%A8%E9%83%A8%E6%96%87%E4%BB%B6%E5%90%8D"><span class="toc-number">14.1.</span> <span class="toc-text">递归输出文件夹里全部文件名</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%AF%BC%E5%87%BA%E4%B8%BAdocx%E6%88%96%E6%B5%81%E6%96%87%E4%BB%B6"><span class="toc-number">14.2.</span> <span class="toc-text">导出为docx或流文件</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%8A%A8%E6%80%81%E5%AF%BC%E5%87%BA%E8%A1%A8%E5%A4%B4"><span class="toc-number">14.3.</span> <span class="toc-text">动态导出表头</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E8%B0%83%E7%94%A8%E5%BE%AE%E4%BF%A1%E6%8E%A5%E5%8F%A3"><span class="toc-number">15.</span> <span class="toc-text">调用微信接口</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E9%9D%A2%E8%AF%95"><span class="toc-number">16.</span> <span class="toc-text">面试</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E9%A1%B9%E7%9B%AE%E4%B8%AD%E6%9C%89%E6%B2%A1%E6%9C%89%E7%94%A8%E5%88%B0AOP%EF%BC%9F"><span class="toc-number">16.1.</span> <span class="toc-text">项目中有没有用到AOP？</span></a></li></ol></li></ol></div></div></div></div></main><footer id="footer"><div id="footer-wrap"><div class="copyright">&copy;2024 By 耶比大熊</div><div class="footer_custom_text">隐约雷鸣 阴霾天空 即使天无雨 我亦留此地<p><a target="_blank" href="https://hexo.io/" style="margin-inline:5px" title="博客框架为Hexo"><img src= "" data-lazy-src="https://img.shields.io/badge/Frame-Hexo-blue?style=flat&amp;logo=hexo" alt="博客框架为Hexo" ></a><a target="_blank" href="https://butterfly.js.org/" style="margin-inline:5px" title="博客主题为Butterfly"><img src= "" data-lazy-src="https://img.shields.io/badge/Theme-Butterfly-6513df?style=flat&amp;logo=bitdefender" alt="博客主题为Butterfly" ></a><a target="_blank" href="https://vercel.com/" style="margin-inline:5px" title="本站采用多线部署，主线路托管于Vercel"><img src= "" data-lazy-src="https://img.shields.io/badge/Hosted-Vercel-brightgreen?style=flat&amp;logo=Vercel" alt="本站采用多线部署，主线路托管于Vercel" ></a><a target="_blank" href="https://icp.gov.moe/?keyword=20245209" style="margin-inline:5px" title="本站已加入萌ICP豪华套餐，萌ICP备20245209号"><img src= "" data-lazy-src="https://img.shields.io/badge/%E8%90%8CICP%E5%A4%87-20245209-ff1485?style=flat&amp;logo=Bitwarden" alt="本站已加入萌ICP豪华套餐，萌ICP备20245209号" ></a><a target="_blank" href="https://github.com/" style="margin-inline:5px" title="本网站源码由Github提供存储仓库托管"><img src= "" data-lazy-src="https://img.shields.io/badge/Source-Github-d021d6?style=flat&amp;logo=GitHub" alt="本网站源码由Github提供存储仓库托管" ></a><a target="_blank" href="http://creativecommons.org/licenses/by-nc-sa/4.0/" style="margin-inline:5px" title="本站采用知识共享署名-非商业性使用-相同方式共享4.0国际许可协议进行许可"><img src= "" data-lazy-src="https://img.shields.io/badge/Copyright-BY--NC--SA%204.0-d42328?style=flat&amp;logo=Claris" alt="本站采用知识共享署名-非商业性使用-相同方式共享4.0国际许可协议进行许可" ></a></p></div></div></footer></div><div id="rightside"><div id="rightside-config-hide"><button id="readmode" type="button" title="阅读模式"><i class="fas fa-book-open"></i></button><button id="translateLink" type="button" title="简繁转换">繁</button><button id="darkmode" type="button" title="浅色和深色模式转换"><i class="fas fa-adjust"></i></button><button id="hide-aside-btn" type="button" title="单栏和双栏切换"><i class="fas fa-arrows-alt-h"></i></button></div><div id="rightside-config-show"><button id="rightside-config" type="button" title="设置"><i class="fas fa-cog fa-spin"></i></button><button class="close" id="mobile-toc-button" type="button" title="目录"><i class="fas fa-list-ul"></i></button><button id="go-up" type="button" title="回到顶部"><span class="scroll-percent"></span><i class="fas fa-arrow-up"></i></button></div></div><div><script src="/js/utils.js?v=4.14.0-b1"></script><script src="/js/main.js?v=4.14.0-b1"></script><script src="/js/tw_cn.js?v=4.14.0-b1"></script><script src="https://cdn.jsdelivr.net/npm/@fancyapps/ui@5.0.35/dist/fancybox/fancybox.umd.min.js"></script><script src="https://cdn.jsdelivr.net/npm/instant.page@5.2.0/instantpage.min.js" type="module"></script><script src="https://cdn.jsdelivr.net/npm/vanilla-lazyload@19.0.5/dist/lazyload.iife.min.js"></script><script src="https://cdn.jsdelivr.net/npm/node-snackbar@0.1.16/dist/snackbar.min.js"></script><script>(() => {
  const panguFn = () => {
    if (typeof pangu === 'object') pangu.autoSpacingPage()
    else {
      btf.getScript('https://cdn.jsdelivr.net/npm/pangu@4.0.7/dist/browser/pangu.min.js')
        .then(() => {
          pangu.autoSpacingPage()
        })
    }
  }

  const panguInit = () => {
    if (false){
      GLOBAL_CONFIG_SITE.isPost && panguFn()
    } else {
      panguFn()
    }
  }

  btf.addGlobalFn('pjaxComplete', panguInit, 'pangu')
  document.addEventListener('DOMContentLoaded', panguInit)
})()</script><div class="js-pjax"></div><script defer src="https://cdn.jsdelivr.net/gh/cxz206015/live2d-widget/autoload.js"></script><script id="canvas_nest" defer="defer" color="0,0,255" opacity="0.7" zIndex="-1" count="30" mobile="false" src="https://cdn.jsdelivr.net/npm/butterfly-extsrc@1.1.3/dist/canvas-nest.min.js"></script><script async data-pjax src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script><div id="local-search"><div class="search-dialog"><nav class="search-nav"><span class="search-dialog-title">搜索</span><span id="loading-status"></span><button class="search-close-button"><i class="fas fa-times"></i></button></nav><div class="is-center" id="loading-database"><i class="fas fa-spinner fa-pulse"></i><span>  数据库加载中</span></div><div class="search-wrap"><div id="local-search-input"><div class="local-search-box"><input class="local-search-box--input" placeholder="搜索文章" type="text"/></div></div><hr/><div id="local-search-results"></div><div id="local-search-stats-wrap"></div></div></div><div id="search-mask"></div><script src="/js/search/local-search.js?v=4.14.0-b1"></script></div></div></body></html>